| Response `kind` | Fields | Answers request kind |
|---|---|---|
| `single_choice` | `selected_value?` (string), `free_text?` (string) | `single_choice` |
| `multi_choice` | `selected_values` (string array) | `multi_choice` |
| `yes_no` | `answer` (boolean) | `yes_no` |
| `free_text` | `text` (string) | `free_text` |
| `credential_added` | `credential_id`, `integration_name`, `auth_type` | `credential_request` |
| `credential_failed` | `integration_name`, `auth_type`, `error_code`, `error_message`, `retryable` (default `true`), `provider_details?` | `credential_request` |
| `skipped` | `reason?` (string) | any (response-only) |
| Status | When | Envelope |
|---|---|---|
| `400` | `resume` body missing `llm`; or `cancel` with no active run | `{"detail": "..."}` |
| `403` | Caller is not the question's originator; or not owner/admin | `{"detail": "..."}` |
| `404` | Chat not found or not in your organization (no existence leak) | `{"detail": "..."}` |
| `409` | `POST /assistant/chat` while a question is pending or a run is in progress | `{"detail": "..."}` |
| `410` | `resume`: question already answered, cancelled, expired, or lost the atomic claim | `{"detail": "..."}` |
| `422` | `resume`: `response` fails discriminated-union validation | FastAPI validation error |
| `402` / `403` / `429` | Billing or rate-limit denial on the turn or resume | `DenialEnvelope` `{code, layer, ...}` |
| Assistant | AI Composer | Workflow builder | |
|---|---|---|---|
| **What you get** | Work done in the chat — answers and completed actions | An editable, reusable workflow graph | An editable, reusable workflow graph |
| **How you drive it** | Plain-language chat | Plain-language chat | Drag, connect, and configure nodes by hand |
| **Touches your workflows?** | No — it has no workflow tools | Yes — it creates and edits the graph | Yes — you are editing the graph |
| **Calls your tools live?** | Yes, directly during the chat | While building, not as a saved run | When you run the workflow |
| **Reusable later?** | The chat is saved; the result is one-off | Yes — the workflow can be run again | Yes — the workflow can be run again |
| **Best for** | One-off tasks and quick questions | Going from idea to a workflow fast | Precise, complex automations |
&message=`
| `error_code` | Meaning |
| --- | --- |
| `oauth_denied` | The user denied access at the provider |
| `oauth_provider_error` | The provider returned an error other than denial |
| `missing_params` | The callback arrived without a `code` or `state` |
| `invalid_state` | The `state` was unknown, expired (>5 min), or already used |
| `token_exchange_failed` | Exchanging the authorization code for tokens failed |
| `credential_creation_failed` | The credential could not be saved |
| `invalid_credentials` | A Composer-linked credential failed its test before auto-resume |
| `internal_error` | An unexpected error occurred |
**Token exchange handles non-standard providers.** The code-for-token exchange sends client credentials either in the request body (`client_secret_post`, the default) or as HTTP Basic auth, depending on the integration's `token_auth_method`. It also handles providers that return a `200` with a `{"ok": false}` body (Slack-style failures) and redacts token values from logs.
### Refreshing OAuth2 tokens
ModuleX keeps OAuth2 access tokens fresh **automatically** at run time. When a credential is resolved for a [tool](/workflow-builder/nodes/tool) or model call and its access token expires within the next 5 minutes, ModuleX refreshes it inline using the stored refresh token and re-encrypts the result before the call proceeds. You do not need to schedule or trigger this.
**Do not rely on a manual or programmatic token refresh.** A manual refresh endpoint and the matching `refreshOAuth2` / `refresh_oauth2` SDK methods exist in the surface, but the path is **known-broken and is not a supported flow**:
- In the ModuleX app, the credential UI's refresh action targets a frontend route that does not exist and **404s before reaching the backend**.
- The backend handler itself has defects that prevent it from completing reliably.
If a credential's authorization has fully lapsed (for example the refresh token was revoked or expired) and automatic refresh cannot recover it, **reconnect the integration** by running the OAuth2 flow again ([`POST /credentials/oauth2/initiate`](#initiate-the-oauth2-flow)). Re-authorizing replaces the stale tokens with a fresh credential. This is the only supported way to restore a lapsed OAuth2 connection. See [Known limitations](/reference/known-limitations).
**Automatic refresh has one parity gap.** The inline run-time refresh always sends client credentials in the request body. A provider that requires HTTP Basic auth for refresh (for example Notion's `token_auth_method: "basic"`) would receive an `invalid_client` error on automatic refresh. For those providers, reconnect via the OAuth2 flow rather than depending on background refresh.
## Encryption at rest
Credential secrets are stored in encrypted text columns and decrypted only in memory at the moment of use. ModuleX uses two distinct schemes, both built on a master `ENCRYPTION_KEY` (required in production, minimum 256 bits). See [Data security & encryption](/security/data-encryption) for the platform-wide picture.
`auth_data` and `oauth_config` are encrypted with a key derived per credential via **HKDF-SHA256**, then sealed with **Fernet** (AES-128-CBC + HMAC-SHA256).
ModuleX OAuth app `client_id`/`client_secret` are encrypted with **PBKDF2-HMAC-SHA256** (100,000 iterations, a random 16-byte salt per value), then Fernet-sealed.
- **Key scoping.** The per-credential key is derived from `(organization_id, credential_id)`, so ciphertext cannot be moved between credentials or organizations — a copied blob simply fails to decrypt.
- **No secret read-back.** Reading a credential returns masked placeholders only: an `oauth2` credential shows the literal `"OAuth2"`; an `api_key` shows a masked key like `sk-proj12…xyz`; a bearer token shows a masked token. The clear-text secret is never returned by any endpoint.
- **Key-version scaffold.** Every encrypted table carries an `encryption_key_version` column (a key-rotation scaffold for SOC 2 CC6.1). It currently defaults to and stays at `1`.
The canonical model class for a stored credential is `OrganizationIntegrationCredential` (the table is `organization_integration_credentials`). It is also exported under the back-compatibility aliases `OrganizationToolCredential` and `OrganizationCredential`.
## Credential resolution at run time
When a tool or model executes, ModuleX must decide **which** credential to use and then prepare it for the outbound call. This happens in two stages.
### Stage 1 — pick a credential
If the run specifies a `credential_id`, ModuleX uses it directly. The credential must match both the organization and the integration; otherwise resolution fails with "no credential found".
Otherwise, ModuleX looks for the credential marked `is_default` for that integration and type.
If there is no default, ModuleX falls back to any valid credential, preferring your **own** credentials over `modulex_key` ones, then the most recently created. If nothing valid exists, resolution fails.
**Precedence, in one line:** explicit `credential_id` → the `is_default` credential → most-recent valid **user** credential → most-recent valid `modulex_key`.
### Stage 2 — prepare for execution
The chosen credential is then prepared depending on its type:
ModuleX decrypts the `auth_data`. For `oauth2` credentials it also checks the access-token expiry and **refreshes inline** if the token expires within 5 minutes (see [Refreshing OAuth2 tokens](#refreshing-oauth2-tokens)). There is **no credit check** on this path — your own keys are billed by the provider, not by ModuleX.
The encrypted blob holds a **UUID pointer, not the real API key**. ModuleX decrypts the pointer, verifies it against the organization's managed-key records, fetches the real key from the system key pool, and runs a **credit-limit check** before use. If the credit limit is exceeded — or there is no active subscription — preparation fails and the call does not proceed. Tool usage on this path is metered after execution.
**Where the billing gate lives.** The credentials CRUD and OAuth endpoints on this page do **not** themselves run a per-call credit gate — they return the standard `{"detail": …}` error shape. The credit gate fires during resolution of `modulex_key` credentials, which happens on the run / composer / assistant / managed-knowledge surfaces. Those surfaces return the flat `DenialEnvelope` (`402`/`403`/`429`) when usage is denied. See [Usage gating & limits](/billing/usage-gating) and [Errors & status codes](/api-reference/errors).
## The credentials API
All paths below are literally `/credentials/...` (the router is mounted with no version prefix). Every route requires owner/admin and the auth headers shown above. Each operation maps to a JavaScript and Python SDK method; see the [SDK ⇄ API parity matrix](/sdks/parity).
| Method & path | JavaScript | Python | Purpose |
| --- | --- | --- | --- |
| `GET /credentials` | `credentials.list` | `credentials.list` | List, grouped by integration (or flat when filtered) |
| `GET /credentials/{id}` | `credentials.get` | `credentials.get` | Get one credential (masked) |
| `POST /credentials` | `credentials.create` | `credentials.create` | Create a credential (type auto-detected) |
| `PUT /credentials/{id}` | `credentials.update` | `credentials.update` | Update display name / metadata |
| `DELETE /credentials/{id}` | `credentials.delete` | `credentials.delete` | Delete a credential (`204`) |
| `POST /credentials/{id}/set-default` | `credentials.setDefault` | `credentials.set_default` | Make default for its integration |
| `POST /credentials/test-temporary` | `credentials.testTemporary` | `credentials.test_temporary` | Validate auth data **before** saving |
| `POST /credentials/{id}/test` | `credentials.test` | `credentials.test` | Test a saved credential |
| `GET /credentials/{id}/usage` | `credentials.usage` | `credentials.usage` | Usage statistics |
| `GET /credentials/{id}/audit` | `credentials.audit` | `credentials.audit` | Audit log entries |
| `POST /credentials/oauth2/initiate` | `credentials.initiateOAuth2` | `credentials.initiate_oauth2` | Start an OAuth2 flow |
| `GET /credentials/oauth2/callback` | — | — | Browser redirect target (no SDK method) |
| `POST /credentials/{id}/oauth2/refresh` | `credentials.refreshOAuth2` | `credentials.refresh_oauth2` | Manual refresh — **broken, do not use** |
| `POST /credentials/mcp-server` | `credentials.mcpServer` | `credentials.create_mcp_server` | Create an MCP server credential |
| `POST /credentials/{id}/refresh-discovery` | `credentials.refreshDiscovery` | `credentials.refresh_mcp_discovery` | Re-discover MCP tools |
| `GET /credentials/{id}/mcp-tools` | `credentials.mcpTools` | `credentials.mcp_tools` | List discovered MCP tools |
| `POST /credentials/bulk-modulex-keys/stream` | `credentials.bulkModulexKeys` | `credentials.bulk_modulex_keys_stream` | SSE: bulk-create `modulex_key` credentials |
### List credentials
`GET /credentials` returns credentials grouped by integration. Supplying `integration_name` switches the response to a flat list for that one integration.
Return a flat list for this integration instead of the grouped shape.
Filter by auth type (for example `oauth2`, `api_key`).
Page size, `1`–`500`.
Number of records to skip. Must be `≥ 0`.
```bash cURL
curl "https://api.modulex.dev/credentials?auth_type=oauth2&limit=50" \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111"
```
```python Python
from modulex import Modulex
async with Modulex(
api_key="mx_live_xxx",
organization_id="11111111-1111-1111-1111-111111111111",
) as client:
grouped = await client.credentials.list(auth_type="oauth2", limit=50)
github = await client.credentials.list(integration_name="github") # flat shape
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_xxx",
organizationId: "11111111-1111-1111-1111-111111111111",
});
const grouped = await client.credentials.list({ authType: "oauth2", limit: 50 });
const github = await client.credentials.list({ integrationName: "github" }); // flat shape
```
```json
{
"integrations": {
"github": {
"integration_name": "github",
"integration_type": "tool",
"total_count": 1,
"auth_types": ["oauth2"],
"credentials": [
{
"credential_id": "b3f1c0de-1111-2222-3333-444455556666",
"integration_name": "github",
"integration_type": "tool",
"display_name": "Production GitHub",
"auth_type": "oauth2",
"is_default": true,
"created_at": "2026-01-19T12:00:00",
"updated_at": "2026-01-19T12:00:00",
"last_used_at": null,
"expires_at": "2026-02-19T12:00:00",
"credentials_metadata": null
}
]
}
},
"total_credentials": 1,
"total_integrations": 1,
"filters": { "auth_type": "oauth2" }
}
```
With `integration_name` set, the response is flat instead:
```json
{
"credentials": [ /* CredentialResponse[] */ ],
"total_count": 1,
"integration_name": "github",
"filters": { "auth_type": null }
}
```
### Create a credential
`POST /credentials` (returns `201`). The credential **type is auto-detected from the body** — you do not pass a route-level type. Match the trigger column from the [authentication types table](#the-six-authentication-types).
The integration to create the credential for (for example `openai`).
The secret material. Its shape selects the type: `{"api_key": "…"}` → `api_key`; `{"token": "…"}` or `{"bearer_token": "…"}` → `bearer_token`; `{"access_token": "…"}` + a top-level `oauth_config` → `oauth2`.
Set explicitly to `modulex_key` or `custom` to select those types. For other types the value is inferred from `auth_data`.
OAuth2 configuration (`token_url`, `client_id`, `client_secret`, …). Required to create an `oauth2` credential directly. Stored encrypted.
Human-readable label.
Set this credential as the default for its integration.
ISO-8601 datetime after which the credential is treated as expired.
```bash cURL
curl -X POST https://api.modulex.dev/credentials \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "openai",
"display_name": "Production OpenAI key",
"make_default": true,
"auth_data": { "api_key": "sk-proj-abc123" }
}'
```
```python Python
from modulex import Modulex
async with Modulex(
api_key="mx_live_xxx",
organization_id="11111111-1111-1111-1111-111111111111",
) as client:
credential = await client.credentials.create(
"openai",
display_name="Production OpenAI key",
make_default=True,
auth_data={"api_key": "sk-proj-abc123"},
)
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_xxx",
organizationId: "11111111-1111-1111-1111-111111111111",
});
const credential = await client.credentials.create({
integrationName: "openai",
displayName: "Production OpenAI key",
makeDefault: true,
authData: { api_key: "sk-proj-abc123" },
});
```
For OAuth2, prefer the [initiate flow](#initiate-the-oauth2-flow) over creating an `oauth2` credential directly — it runs PKCE and the code exchange for you.
### Test a credential
Two operations validate credentials against the integration's configured test endpoint:
- `POST /credentials/test-temporary` validates auth data **before** you save it. It takes `integration_name`, `auth_type`, and `auth_data`.
- `POST /credentials/{id}/test` validates a **saved** credential. An expired credential returns `is_valid: false` with "Credential has expired".
A test response reports `is_valid`, a human-readable `message`, `tested_at`, and a `test_method` of `api_call`, `basic`, or `none`. Integrations without a configured test endpoint report `test_method: "none"` and `is_valid: true` with a "no test endpoint" message rather than failing.
```bash cURL
curl -X POST https://api.modulex.dev/credentials/test-temporary \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "tavily",
"auth_type": "api_key",
"auth_data": { "api_key": "tvly-abc123" }
}'
```
```python Python
result = await client.credentials.test_temporary(
"tavily",
"api_key",
{"api_key": "tvly-abc123"},
)
saved = await client.credentials.test("b3f1c0de-1111-2222-3333-444455556666")
```
```javascript JavaScript
const result = await client.credentials.testTemporary({
integrationName: "tavily",
authType: "api_key",
authData: { api_key: "tvly-abc123" },
});
const saved = await client.credentials.test("b3f1c0de-1111-2222-3333-444455556666");
```
### Set default, update, and delete
- `POST /credentials/{id}/set-default` makes a credential the default for its integration and unsets the previous default.
- `PUT /credentials/{id}` updates only `display_name` and `metadata`. Secrets are immutable through this route — to change a secret, reconnect (OAuth2) or create a new credential and delete the old one. There is no rotate endpoint.
- `DELETE /credentials/{id}` permanently deletes a credential and returns `204 No Content`.
```bash cURL
# Make default
curl -X POST https://api.modulex.dev/credentials/b3f1c0de-1111-2222-3333-444455556666/set-default \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111"
# Delete (204)
curl -X DELETE https://api.modulex.dev/credentials/b3f1c0de-1111-2222-3333-444455556666 \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111"
```
```python Python
await client.credentials.set_default("b3f1c0de-1111-2222-3333-444455556666")
await client.credentials.update(
"b3f1c0de-1111-2222-3333-444455556666",
display_name="GitHub (CI)",
)
await client.credentials.delete("b3f1c0de-1111-2222-3333-444455556666")
```
```javascript JavaScript
await client.credentials.setDefault("b3f1c0de-1111-2222-3333-444455556666");
await client.credentials.update("b3f1c0de-1111-2222-3333-444455556666", {
displayName: "GitHub (CI)",
});
await client.credentials.delete("b3f1c0de-1111-2222-3333-444455556666");
```
## MCP server credentials
A credential can also point at an external [Model Context Protocol (MCP) server](/integrations/building/custom-mcp). Creating one connects to the server (over `streamable_http` by default), discovers its tools, and stores the catalog in `credentials_metadata`. MCP server credentials are persisted with `integration_name: "mcp_server"` and `auth_type: "custom"`.
The MCP server's URL.
Headers to send when connecting, for example `{"Authorization": "Bearer mcp-token"}`.
Label for the credential.
Set as default.
```bash cURL
curl -X POST https://api.modulex.dev/credentials/mcp-server \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111" \
-H "Content-Type: application/json" \
-d '{
"server_url": "https://mcp.example.com/sse",
"display_name": "Internal MCP",
"headers": { "Authorization": "Bearer mcp-token" }
}'
```
```python Python
mcp = await client.credentials.create_mcp_server(
"https://mcp.example.com/sse",
display_name="Internal MCP",
headers={"Authorization": "Bearer mcp-token"},
)
tools = await client.credentials.mcp_tools(mcp.credential_id)
refreshed = await client.credentials.refresh_mcp_discovery(mcp.credential_id)
```
```javascript JavaScript
const mcp = await client.credentials.mcpServer({
serverUrl: "https://mcp.example.com/sse",
displayName: "Internal MCP",
headers: { Authorization: "Bearer mcp-token" },
});
const tools = await client.credentials.mcpTools(mcp.credential_id);
const refreshed = await client.credentials.refreshDiscovery(mcp.credential_id);
```
- `GET /credentials/{id}/mcp-tools` returns the discovered tool list and a total count.
- `POST /credentials/{id}/refresh-discovery` re-discovers tools and reports what was added or removed. It is valid only for `mcp_server` credentials; calling it on any other credential returns `400`.
## Errors
Credentials endpoints return the standard `{"detail": ""}` HTTPException envelope. There is **no `402`** on these routes — credit denial happens during run-time resolution, not on these CRUD calls (see [Where the billing gate lives](#stage-2--prepare-for-execution)). The status codes you will see across this subsystem:
| Status | When |
| --- | --- |
| `201` | Credential created |
| `204` | Credential deleted |
| `302` | OAuth2 callback redirect (always, even on error) |
| `400` | Validation error, unsupported auth, malformed body |
| `401` / `403` | Missing/invalid auth, not a member, or not owner/admin |
| `404` | Credential or integration not found |
| `429` | Organization rate limit (with `X-RateLimit-*` and `Retry-After` headers; fail-open) |
| `500` | Unexpected server error |
| `503` | OAuth state storage (Redis) unavailable on initiate |
See [Errors & status codes](/api-reference/errors) for the full error model across surfaces and [SDK errors & retries](/sdks/errors-retries) for how the SDKs surface them.
## Where to go next
The connect-it walkthrough and the six integration auth schema variants.
Create, scope, and rotate credentials in the app and via the API.
How ModuleX encrypts credentials and manages keys platform-wide.
Documented gaps, including the broken manual OAuth2 refresh path.
---
# Credits & the billing model
URL: https://docs.modulex.dev/concepts/credits-billing
How ModuleX meters managed usage in credits, what spends them, the difference between managed and bring-your-own-key usage, and where the billing gate can pause a run.
ModuleX charges for **managed usage** in **credits**. A credit is a small, fixed
unit of value: **100 credits = $1.00**, so one credit is worth $0.01. Your plan
includes a monthly credit allowance, and managed work — running a workflow,
chatting with the [Assistant](/concepts/assistant), retrieving from managed
knowledge, calling a tool — draws down that allowance as you go.
This page is the mental model: where credits come from, what spends them, what is
free, and what happens when the allowance runs out. For the exact metering rules
and the wallet mechanics, follow the links to
[Credits & metering](/billing/credits) and the
[Billing & credits overview](/billing/overview).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1160 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** A single flow diagram showing where credits come from and where they go.
**[IMAGE_DETAILS]:** Left to right: a "Plan allowance" box (monthly credits) feeding into a "Usage" column listing managed actions (Run / Assistant turn / Tool call / Managed knowledge retrieval & ingest). Below the plan box, a smaller "Wallet (prepaid)" box labeled "used after the allowance runs out, if overage is on." An arrow from Usage passes through a gate icon labeled "Usage gate (checks before each action)" before reaching a "Result" node. Off to the side, a separate, greyed-out lane labeled "BYOK — billed by your provider, not in credits." Light theme, 16:9, clean line icons, no UI chrome. Annotate the credit unit "100 credits = $1.00".
## Credits in one minute
The unit ModuleX uses to meter managed usage. **100 credits = $1.00**
(1 credit = $0.01). Allowances and the wallet are both counted in credits.
Your [plan](/billing/plans) grants a monthly credit allowance. When that runs
out, a paid organization with overage turned on can keep going using a prepaid
[wallet](/billing/wallet).
Managed work: a workflow [run](/concepts/workflows-and-runs), an Assistant
turn, a tool call, and managed-knowledge retrieval and ingest. See
[what costs credits](#what-costs-credits).
[Bring-your-own-key (BYOK)](#managed-versus-byok-usage) usage is not charged in
credits — your own provider bills you directly.
**The credit value is fixed.** 100 credits always equal $1.00. Each paid plan
includes a monthly credit allowance — for example, the $25/month plan includes 5,000
credits ($50 of managed usage), and the $100/month plan includes 20,000 credits
($200). See [Plans & pricing](/billing/plans) for current figures.
## What costs credits
Credits are spent on **managed** actions — work ModuleX runs for you on
ModuleX-provisioned providers. The table below is the plain-language summary;
[Credits & metering](/billing/credits) has the exact per-action numbers.
| Managed action | What it costs |
| --- | --- |
| Run a workflow, or take one Assistant turn | A flat base charge per run or turn, plus the cost of any model usage inside it. A turn is one message you send and the response it produces. |
| Use a language model on managed credentials | Metered by tokens — input and output — at the model's rate, with a small system margin applied. |
| Call an integration [tool](/workflow-builder/nodes/tool) | A flat base charge per tool call. |
| Retrieve from managed ([modulexdb](/integrations/knowledge-providers/modulexdb)) knowledge | A flat base charge per search, plus the cost of embedding your query. |
| Ingest a document into managed knowledge | A flat base charge per document, plus the cost of embedding its text. Retrying an unchanged document does not charge again. |
**Resuming does not double-charge.** Each turn is charged exactly once. When the
Assistant or a workflow pauses for [human-in-the-loop](/realtime/hitl) approval and
then continues, resuming the same turn is not charged a second time.
### What does not cost credits
Model and tool calls made on **your own** provider accounts are tracked for
analytics only — never billed in credits. See
[managed versus BYOK](#managed-versus-byok-usage).
Retrieval and ingest on a knowledge base backed by **your own** vector store
(Qdrant, Pinecone, MongoDB Atlas, or Weaviate) are not charged by ModuleX.
Browsing workflows, editing the canvas, viewing runs, and managing settings
are not metered in credits.
Designing a workflow does not spend credits. Credits apply when managed work
actually executes.
## Managed versus BYOK usage
Every model, tool, and knowledge action runs in one of two modes. The mode decides
whether ModuleX meters it in credits.
ModuleX provides the model, tool, or vector store on your behalf — the managed
providers are **modulexai** (models and tools) and **modulexdb** (knowledge).
**Managed usage is billed in credits.**
You connect your own provider accounts and ModuleX uses your keys. **BYOK usage
is not charged in credits** — your provider bills you directly, with no ModuleX
markup.
**The rule in one line.** Managed (modulexai / modulexdb) usage spends credits.
BYOK usage is uncosted by ModuleX and tracked for analytics only. For how to
connect your own providers, see [LLM providers](/integrations/llm-providers/overview)
and [external knowledge providers](/platform/knowledge/external-providers).
## When the allowance runs out
Credits are drawn first from your plan's monthly allowance. What happens next
depends on your plan and settings.
Managed usage draws down your monthly credit allowance until it reaches zero.
If you are on a paid plan and have **overage** turned on, further managed usage
is funded by your prepaid [wallet](/billing/wallet). You can top the wallet up
manually, or set auto top-up to refill it before it runs dry.
Without an allowance or a funded wallet, the next managed action is declined
rather than billed silently. See [the usage gate](#the-usage-gate-when-a-run-is-paused).
For the full mechanics — how the wallet works, overage, top-ups, and auto top-up —
see [Wallet & top-ups](/billing/wallet) and [Credits & metering](/billing/credits).
## The usage gate: when a run is paused
ModuleX checks your credit and limit status **before** it starts a piece of managed
work. This check is the **usage gate**, and it is live today. If you do not have
the budget or are over a limit, the gate declines the action up front — so you are
never charged for work that could not run.
The gate applies on the **managed-usage surfaces**: starting a workflow
[run](/concepts/workflows-and-runs), using the [AI Composer](/concepts/ai-composer),
taking an [Assistant](/concepts/assistant) turn, and managed-knowledge retrieval
and ingest. Plain read-and-manage actions — listing workflows, editing settings,
viewing runs — do **not** go through this gate.
**Where the gate does and does not apply.** A billing denial can appear on the
managed-run surfaces above. It does **not** appear on ordinary
list/create/update/delete and organization-settings requests, which use a
different, plain error shape. See
[Errors & status codes](/api-reference/errors) for the exact shapes.
When the gate declines an action, ModuleX returns a billing denial. There are three
kinds, by what was exceeded:
Your plan allowance is used up and the wallet cannot cover the action (no
overage, or an empty or insufficient balance). Top up the
[wallet](/billing/wallet) or [upgrade your plan](/billing/plans).
You have hit a plan limit on a resource, such as the number of knowledge bases.
Upgrade or free up the resource.
You are sending managed requests faster than your plan's per-minute rate. Slow
down and retry; the response tells you how long to wait.
Each billing denial is a structured response that tells you exactly what was hit —
the kind of limit, the value, and the cap — so you can react automatically. The
full response shape and how to handle it in code live on
[Usage gating & limits](/billing/usage-gating) and
[Errors & status codes](/api-reference/errors).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1161 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The in-app message a user sees when the usage gate declines a managed action.
**[SCREENSHOT_DETAILS]:** Capture the "out of credits" state in the ModuleX app — for example, attempting an Assistant turn or a workflow run with the plan allowance exhausted and no wallet overage. Show the inline notice that explains the action was paused (not silently charged) with a clear path to top up or upgrade. Crop to the notice and surrounding context, light theme, no personal data. If the empty-credit state cannot be reproduced, mark this as a synthetic mock built from the real component.
## How it fits together
The whole billing picture: plans, credits, the wallet, and the gate.
Free, Pro, Max, and Enterprise — allowances, limits, and pricing.
The exact rules for what a credit is and what each action costs.
The admission gate and its 402 / 403 / 429 responses, in detail.
---
# Knowledge & RAG
URL: https://docs.modulex.dev/concepts/knowledge-rag
How ModuleX retrieves your company knowledge: knowledge bases, managed (modulexdb) versus bring-your-own-key storage, and the ingest and retrieval flow that powers RAG.
ModuleX uses **retrieval-augmented generation (RAG)** to ground answers in your own
content. You upload documents to a **knowledge base**, ModuleX prepares them for
search, and your chats, the [Assistant](/concepts/assistant), and your
[workflows](/concepts/workflows-and-runs) can then retrieve the most relevant
passages on demand — so responses cite your material instead of guessing.
This page explains the ideas you need: what a knowledge base is, the difference
between managed and bring-your-own storage, and the two halves of RAG — getting
content in (ingest) and getting answers out (retrieval).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1130 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** A single diagram showing the two halves of RAG side by side — ingest on the left, retrieval on the right.
**[IMAGE_DETAILS]:** Left "Ingest" lane: a document icon → Parse → Chunk → Embed → stored as vectors in a knowledge base. Right "Retrieve" lane: a user question → Embed query → vector search over the same knowledge base → top matching chunks returned to a chat / Assistant / workflow. Show the knowledge base in the center connecting both lanes. Horizontal layout, light theme, 16:9, clean line icons, no UI chrome. Label the center store "Knowledge base (managed = modulexdb, or your own vector store)".
## What a knowledge base is
A **knowledge base** is a named collection of your documents that ModuleX has
prepared for search. Think of it as one searchable library: a set of product
manuals, a policy handbook, or a folder of support articles.
Each knowledge base carries its own settings for how documents are split and how
they are turned into searchable vectors, so you can tune one library for long
reference PDFs and another for short snippets — without affecting the rest.
The files you upload. Each one moves through the [ingest](#getting-content-in-ingest)
pipeline and ends up searchable.
Each document is split into smaller passages. Retrieval returns chunks, not
whole files, so answers stay focused.
Every chunk is converted to a numeric vector that captures its meaning, which
is what makes search by meaning possible.
You can manage knowledge bases in the app or over the API. For the hands-on
walkthrough, see [Knowledge overview](/platform/knowledge/overview) and the
[Build a RAG knowledge base](/guides/build-a-knowledge-base) guide.
Throughout these docs the feature is called **Knowledge** (singular). A single
library is a **knowledge base**, often shortened to **KB**.
## Managed versus bring-your-own storage
When you create a knowledge base, you choose where the vectors live. This choice
decides both who hosts the storage and how usage is billed.
ModuleX hosts the vector storage for you with the built-in **modulexdb**
provider. Nothing to set up. **Ingest and retrieval are metered in
[credits](/billing/credits).**
Point a knowledge base at a vector store you already run. ModuleX reads and
writes to it, and **usage on your own store is not charged in credits** —
your provider bills you directly.
### Managed knowledge: modulexdb
Managed knowledge bases use ModuleX's hosted vector store, **modulexdb**. They are
the fastest way to start because there is no external account to connect. Because
ModuleX runs the storage and the embedding calls on your behalf, **each retrieval
and each document ingest spends credits** (see [How credits apply](#how-credits-apply)).
### Bring your own key (BYOK)
If you already operate a vector database, you can connect it and keep your data in
your own infrastructure. ModuleX supports these external knowledge providers:
Use a Qdrant cluster as your vector store.
Use a Pinecone index as your vector store.
Use MongoDB Atlas Vector Search.
Use a Weaviate instance as your vector store.
**Billing in one line.** Managed (modulexdb) knowledge is billed in credits.
BYOK knowledge is uncosted by ModuleX — it is tracked for analytics only, and any
charges come from your own provider. See [Credits & metering](/billing/credits).
## Getting content in: ingest
**Ingest** is the one-time preparation each document goes through after you upload
it. ModuleX runs it in the background so you can keep working while large files
process.
You add a file to a knowledge base. Supported formats include PDF, Word
(`.docx` / `.doc`), plain text, Markdown, HTML, CSV, JSON, Excel (`.xlsx`),
and PowerPoint (`.pptx`).
ModuleX extracts the readable text from the file, whatever its format.
The text is split into smaller passages using the knowledge base's chunking
settings, so each piece is a focused, retrievable unit.
Each chunk is converted into an embedding — a vector that represents its
meaning — and stored alongside the text in the knowledge base.
### Watching a document process
Every document reports its progress, so you always know whether it is ready to
search.
A document moves through these states:
- **Pending** — uploaded and waiting in the queue.
- **Processing** — being parsed, chunked, and embedded.
- **Completed** — fully ingested and ready to retrieve.
- **Failed** — something went wrong during ingest. You can fix the source file
and retry the document; retrying a document does not re-charge an unchanged
ingest.
For managing and monitoring documents in the app, see
[Managing documents](/platform/knowledge/documents).
## Getting answers out: retrieval
**Retrieval** happens every time something asks a question. ModuleX turns the
question into an embedding, compares it against the stored chunks, and returns the
closest matches. Those passages are then handed to the model so its answer is
grounded in your content.
ModuleX offers a few retrieval styles for different needs:
Finds chunks by meaning, even when the wording differs from the question.
This is the default style.
Blends meaning-based search with exact keyword matching, which helps with
names, codes, and acronyms.
Searches several knowledge bases at once and merges the best results.
Returns a ready-to-use block of text, assembled from the top chunks within a
token budget, for dropping straight into a prompt.
### Where retrieval shows up
You rarely call retrieval by hand. It runs wherever an answer should come from
your own material:
Ask a question in chat and get an answer drawn from your documents.
The Assistant retrieves from your knowledge as one of the tools it can use.
Add a step to a workflow that retrieves from a knowledge base.
### Retrieving over the API
If you build on ModuleX directly, you can run a search against a knowledge base
yourself. Authenticate every request with your API key and organization, exactly
as on every other endpoint (see [Authentication](/api-reference/authentication)).
```bash cURL
curl -X POST https://api.modulex.dev/knowledge-bases/7c1e9b2a-4f3d-4a21-9c77-2b1e0f9a3c44/search \
-H "Authorization: Bearer mx_live_8Kd2pQ7rExample" \
-H "X-Organization-ID: org_3xampleOrg42" \
-H "Content-Type: application/json" \
-d '{
"query": "What is our refund policy?",
"top_k": 5,
"min_score": 0.2
}'
```
```python Python
import asyncio
from modulex import Modulex
async def main():
async with Modulex(
api_key="mx_live_8Kd2pQ7rExample",
organization_id="org_3xampleOrg42",
) as mx:
results = await mx.knowledge.search(
"7c1e9b2a-4f3d-4a21-9c77-2b1e0f9a3c44",
"What is our refund policy?",
top_k=5,
)
for match in results.matches:
print(match.score, match.content)
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from "modulex";
const client = new Modulex({
apiKey: "mx_live_8Kd2pQ7rExample",
organizationId: "org_3xampleOrg42",
});
const results = await client.knowledge.search(
"7c1e9b2a-4f3d-4a21-9c77-2b1e0f9a3c44",
{ query: "What is our refund policy?", topK: 5, minScore: 0.2 },
);
for (const match of results.matches) {
console.log(match.score, match.content);
}
```
A successful search returns the matching chunks ranked by relevance:
```json Response
{
"query": "What is our refund policy?",
"knowledge_base_id": "7c1e9b2a-4f3d-4a21-9c77-2b1e0f9a3c44",
"top_k": 5,
"total_matches": 3,
"matches": [
{
"chunk_id": "c1a2b3c4-...",
"document_id": "d9e8f7a6-...",
"document_filename": "refund-policy.pdf",
"chunk_index": 4,
"score": 0.83,
"content": "Refunds are available within 30 days of purchase...",
"metadata": {}
}
]
}
```
On a **managed (modulexdb)** knowledge base, a search that would exceed your plan
allowance can return a billing denial instead of results — a `402`, `403`, or
`429` response. See [Usage gating & limits](/billing/usage-gating) and
[Errors & status codes](/api-reference/errors) for the response shape and how to
handle it.
## How credits apply
Credits are only spent on **managed (modulexdb)** knowledge. BYOK knowledge bases
are not charged by ModuleX. One credit is a small, fixed unit of managed usage
(100 credits = $1.00).
| Action on a managed knowledge base | What it costs |
| --- | --- |
| Ingest a document | A flat base charge per document, plus the cost of embedding its text. Retrying an unchanged document does not re-charge. |
| Run a retrieval (any search style) | A flat base charge per search, plus the cost of embedding the query. |
On a **BYOK** knowledge base, neither ingest nor retrieval spends credits.
For the full pricing model — how credits are metered, the wallet, and overage —
see [Credits & metering](/billing/credits) and
[Billing & credits overview](/billing/overview).
## Plan limits
Your plan sets how many knowledge bases you can keep, how large each uploaded file
can be, and how many documents each knowledge base holds. The values below come
from the current subscription plan configuration.
| Limit | Free | Pro | Max | Enterprise |
| --- | --- | --- | --- | --- |
| Knowledge bases | 10 | 3 | 50 | Unlimited |
| Max file size per upload | 10 MB | 50 MB | 100 MB | Unlimited |
| Documents per knowledge base | 100 | 1,000 | 1,000 | Unlimited |
The **Pro** knowledge-base count (3) is lower than **Free** (10) in the current
plan configuration. This is a known inconsistency in the source data, shown here
as-is — confirm the limit that applies to your organization on the
[Plans & pricing](/billing/plans) page before relying on it. The per-upload file
size is set by your **plan**, not a single fixed cap.
## Where to go next
Create and manage knowledge bases in the ModuleX app.
A start-to-finish guide: create a knowledge base, ingest documents, and query
it.
How ModuleX-hosted vector storage and retrieval work.
Connect Qdrant, Pinecone, MongoDB Atlas, or Weaviate.
---
# Organizations, roles & membership
URL: https://docs.modulex.dev/concepts/organizations-roles
How tenancy works in ModuleX: the organization is your workspace and billing boundary, the X-Organization-ID header scopes every request, and the two live roles are owner and admin.
Everything you do in ModuleX happens inside an **organization**. It is your shared workspace and your billing boundary at the same time: your workflows, credentials, knowledge bases, plan, wallet, and credits all belong to one organization, and every run is metered against it.
This page explains the three ideas you need to work confidently across a team: what an organization is, how ModuleX knows which one you are acting in, and the two roles that decide who can do what. For the request-level detail, follow the links to [Org context & X-Organization-ID](/security/org-context) and [Roles & permissions](/security/roles-permissions).
## The three ideas on this page
Your workspace and billing boundary. Every resource and every charge belongs to one organization.
The `X-Organization-ID` header tells ModuleX which organization a request runs in.
Each member is an **owner** or an **admin**. There is no member role.
## The organization: your workspace and billing boundary
An organization is a tenant. It is the line ModuleX draws around your work so that your data, your access, and your bill all stay together and stay separate from everyone else's.
Workflows, [credentials](/concepts/credentials-oauth), [knowledge bases](/concepts/knowledge-rag), and chats live inside an organization. Members of that organization share them.
The plan, the credit allowance, and the prepaid wallet belong to the organization — not to an individual. Every run is metered against the organization it runs in.
You can belong to more than one organization — for example a personal workspace and a team workspace — and you can own up to **five** organizations. Each one is fully separate: switching between them swaps your entire set of resources, plan, and credits.
You never create an account by hand on the API side. ModuleX uses a single identity provider (Clerk) for sign-in, and your ModuleX user and a default personal organization are created automatically the first time you sign in. See [Just-in-time provisioning](#how-you-get-your-first-organization) below.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1150 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** A diagram showing one organization as a boundary that contains a user's resources and billing.
**[IMAGE_DETAILS]:** One illustration (not a screenshot), 16:9, light theme, ModuleX brand palette. Draw a single rounded rectangle labeled "Organization (workspace + billing boundary)". Inside it, two stacked groups: a "Resources" group with small labeled chips (Workflows, Credentials, Knowledge bases, Chats) and a "Billing" group with chips (Plan, Credit allowance, Wallet). Above the boundary show two person icons labeled "owner" and "admin" pointing into it. To the right, show a second, separate, greyed-out organization boundary to convey isolation between organizations. Minimal text inside shapes.
## The org context: which organization am I in?
Because you can belong to several organizations, every action has to say which one it applies to. ModuleX calls this the **org context**, and on the API it is carried by one header: **`X-Organization-ID`**.
In the [ModuleX app](/platform/overview) you set the org context with the organization switcher, and the app sends the header for you. When you call the API or use an [SDK](/sdks/overview), you set it yourself.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1151 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The organization switcher in the ModuleX app.
**[SCREENSHOT_DETAILS]:** Capture from the live ModuleX app. Show the organization switcher control (the menu where a user picks the active organization), expanded to reveal the list of organizations the user belongs to, with the currently active one highlighted. Light theme. Crop tightly to the switcher and its surrounding header; redact any real organization names. Annotate with a single callout arrow pointing at the active organization labeled "This sets your org context".
### Org context in API and SDK calls
Every org-scoped request carries two headers: your API key as a bearer token, and the organization the request runs in. The example below lists the workflows in one organization.
```bash cURL
curl https://api.modulex.dev/workflows \
-H "Authorization: Bearer mx_live_2f9c4a1b8e7d6c5a4b3f2e1d0c9b8a76" \
-H "X-Organization-ID: 8a1f3c2e-9b4d-4e7a-bc11-7d6e5f4a3b2c"
```
```python Python
import asyncio
from modulex import Modulex
async def main():
async with Modulex(
api_key="mx_live_2f9c4a1b8e7d6c5a4b3f2e1d0c9b8a76",
organization_id="8a1f3c2e-9b4d-4e7a-bc11-7d6e5f4a3b2c",
) as client:
workflows = await client.workflows.list()
print(workflows)
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_2f9c4a1b8e7d6c5a4b3f2e1d0c9b8a76",
organizationId: "8a1f3c2e-9b4d-4e7a-bc11-7d6e5f4a3b2c",
});
const workflows = await client.workflows.list();
console.log(workflows);
```
If you omit `X-Organization-ID` on an org-scoped endpoint, the request is rejected with a `400` and the message `X-Organization-ID header is required`. If you are a member of the organization but not allowed to perform the action, you get a `403`. See [Authentication](/api-reference/authentication) for how the two headers fit together and [Errors & status codes](/api-reference/errors) for the full response shapes.
You can also set a default organization once on the client and override it per call. The exact header handling, the SDK precedence rules, and how an API key can be scoped to a single organization are covered in [Org context & X-Organization-ID](/security/org-context).
## Roles: owner and admin
Membership in an organization comes with a **role**. ModuleX has exactly two live roles.
The role assigned to whoever creates the organization. Owners can do everything an admin can, plus owner-only actions such as removing members. An owner cannot leave their own organization.
Full working access to the organization: build and run workflows, use the AI Composer and the Assistant, manage credentials and knowledge, and invite teammates. New members join as admins.
There is **no member role**. A `member` role existed in earlier versions of ModuleX and was retired on 2026-06-20. The live roles are **owner** and **admin** only, and the API rejects any attempt to invite or set a role other than `admin`. If you see "member" referenced anywhere, treat it as legacy.
The `owner` role is assigned only at the moment an organization is created; it is not something you set when inviting or updating a teammate. Every invited or updated member is an admin.
### What requires owner or admin
Because the two live roles both have broad working access, most day-to-day actions are available to either role. A few of ModuleX's most capable surfaces require an owner or admin explicitly, and a small set of governance actions are owner-only.
The following surfaces require the caller to be an **owner or admin** of the active organization:
- The [AI Composer](/concepts/ai-composer) (turning plain English into a workflow).
- The [Assistant](/concepts/assistant) (the agentic chat that calls your tools).
- [Workflow schedules](/workflow-builder/execution/schedule) and related management.
- Organization settings, the LLM catalog, and inviting teammates.
A caller who is authenticated and a member of the organization but lacks the required role receives a `403`.
A few governance actions are reserved for the **owner**:
- Removing another member from the organization.
- Owners cannot leave their own organization (transfer ownership or remove the organization instead).
Source-of-truth: this owner/admin model is enforced by the backend on every request. For the per-endpoint permission map — which routes require `organization_admin_required` versus `organization_owner_required` — see [Roles & permissions](/security/roles-permissions). Note that the in-app interface may optimistically show edit controls before the backend confirms your role; the server always enforces the real role on each call.
## How you get your first organization
You do not sign up through a ModuleX form. The first time you sign in, ModuleX provisions everything you need automatically — this is **just-in-time (JIT) provisioning**.
You authenticate through ModuleX's identity provider (Clerk). The backend verifies your token; there is no separate ModuleX password or login endpoint.
On your first valid sign-in, ModuleX creates your user record and a personal default organization, and makes you its **owner** — all in one step, so a second concurrent request never creates a duplicate.
The new organization is seeded with sensible defaults so you can start immediately, and you land in it as the active org context.
Your personal organization is named from the first available of your first name, your username, or the part of your email before the `@`. If none is available, it is named `My Workspace`.
JIT provisioning happens for sign-in (your user identity). It does **not** apply to API keys: a key cannot exist before your user does, and creating an API key requires signing in first. See [Quickstart](/get-started/quickstart) to create your first key.
## Working as a team
When you are ready to collaborate, you add people to an organization by **inviting** them.
Invite a teammate by email. They join as an **admin**. Each invitation is valid for **7 days**.
Only the invited email address can accept the invitation. Once accepted, they become a member of the organization with the admin role.
The new admin shares the organization's workflows, credentials, knowledge, and billing. Owners can later remove a member; admins cannot.
Inviting teammates is a paid capability. On the **Free** plan, sending an invite is declined with a `403` and the reason `TEAMMATES_NOT_ALLOWED`. Upgrade to **Pro** or higher to invite teammates. See [Plans & pricing](/billing/plans) for what each plan includes.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1152 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** Inviting a teammate to an organization and the teammate accepting.
**[APP_VIDEO_DETAILS]:** Screen recording from the live ModuleX app, ~30–45s, light theme, 16:9. Show an owner or admin opening the team/members area, sending an invite by email, and the resulting pending invitation. Then cut to the invited person's view accepting the invitation and landing in the shared organization as an admin. Redact real email addresses and organization names. Annotate the moment the new member appears in the members list with a callout "Joins as admin".
## How this connects to the rest of ModuleX
The request-level detail: how the org context header is read, how API-key org scope is enforced, and what happens when it is missing.
The per-endpoint permission map — exactly which actions require owner or admin.
How managed usage is metered in credits against the organization, and where the billing gate applies.
How chats can be kept personal or shared across the organization.
---
# How ModuleX works
URL: https://docs.modulex.dev/concepts/overview
The end-to-end mental model behind ModuleX: you author a workflow, you run it, and you observe the run live as each step streams its progress.
ModuleX runs on one loop you will see everywhere in these docs: **you author a workflow, you run it, and you observe the run as it happens.** Once that loop clicks, every other feature is a deeper version of one of those three steps.
This page is the mental model. It does not teach you every setting — it shows you the shape of the whole system so the rest of the docs have somewhere to hang. For the term-by-term map, see [Core concepts at a glance](/get-started/core-concepts).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1080 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** A single end-to-end flow diagram showing the author → run → observe loop.
**[IMAGE_DETAILS]:** One illustration (not a screenshot). Left-to-right flow in three labeled stages. Stage 1 "Author" shows two inputs converging on a workflow graph: a chat bubble labeled "AI Composer (plain English)" and a hand-drawn canvas labeled "Visual builder". Stage 2 "Run" shows the graph executing node by node, with a small ticket labeled "run". Stage 3 "Observe" shows a live event stream (stacked event chips: metadata, node update, done) flowing back to a person. Add a thin badge beneath Stage 2 reading "credit check before start" and a side note "can pause for your input". 16:9, light theme, ModuleX brand palette, minimal text inside shapes.
## The loop in one line
Describe a process to the AI Composer, or build it on the visual canvas. Both produce the same editable **workflow** graph.
Start a **run** from chat, the API, or an SDK. ModuleX checks your credit and capacity, then executes the graph step by step.
Watch the run stream its progress event by event, pause it for your input when needed, and inspect the final result.
There is a shortcut, too: the [Assistant](/concepts/assistant) collapses all three steps into one chat. You give it a goal, it picks and runs the tools itself, and you watch the same live stream — no workflow to author first. More on that below.
## Step 1 — Author a workflow
A **workflow** is an editable graph that connects tools, data, and agents into a repeatable process. You build it one of two ways, and both ways edit the same graph.
Tell the **AI Composer** what you want in plain English. It turns your description into a complete, editable workflow graph, then keeps editing the canvas as you chat with it.
Open the **workflow builder** and place nodes by hand. You connect steps, set their options, and pass data between them with references.
A workflow is assembled from a fixed set of **nine node types** — each step does one thing and writes its result back into the run so later steps can use it. You connect steps with edges, and you move data between them with a **reference** written `{{node_id.field}}`. You do not need the details now; the [workflow engine](/concepts/workflow-engine) and the [node types overview](/workflow-builder/nodes/overview) cover them in depth.
Authoring is multi-user. Several people can edit the same canvas at once, with live cursors, presence, and node locks so edits never collide. See the [realtime and collaboration model](/concepts/realtime-model).
## Step 2 — Run it
A **run** is one execution of a workflow. You can start a run from three places, and the result is the same execution either way.
Trigger a workflow inside a chat and watch it run there.
Run a workflow programmatically over REST and stream the result.
Run from your own code with the official JavaScript or Python client.
### What happens when you press run
Before any work starts, ModuleX runs a quick admission check: do you have the credit and the capacity to run right now? If yes, the run proceeds. If not, the request is declined cleanly with a billing error — nothing partial executes. This check applies to runs, AI Composer turns, Assistant turns, and managed-knowledge calls.
ModuleX accepts the request and hands back a **run id** along with a stream you can listen on. The actual execution happens in the background, so the response comes back immediately.
The engine walks the graph from its entry point. Every node does its work — calling a model, retrieving from a knowledge base, calling an integration tool, branching, and so on — and writes its result into the run state for the next step to read.
The run ends in one of a small set of outcomes — it completes, it fails, or it is cancelled. Some runs pause partway to ask you a question first (see [Observe](#step-3-observe-the-run)).
The admission check is real and live on the run, AI Composer, Assistant, and managed-knowledge surfaces. When it declines a request you get a `402`, `403`, or `429` response carrying a structured reason ([usage gating & limits](/billing/usage-gating)). Plain create, read, update, delete, and organization-settings calls are not gated this way — they return a simpler error shape. See [Errors & status codes](/api-reference/errors) for both.
### What a run costs
ModuleX meters **managed** usage in [credits](/billing/credits). Each run is a flat charge, plus the managed model and managed-retrieval usage it consumes along the way. If you bring your own model keys, that usage is billed by your provider and is not metered as credits. The [credits and billing model](/concepts/credits-billing) explains exactly what consumes credits.
## Step 3 — Observe the run
You do not wait blindly for a result. While a run executes, it **streams** its progress to you event by event over Server-Sent Events (SSE) — so you can watch each step happen live, in the app or from your own code.
The run emits a sequence of events as it goes: a metadata event when it starts, a node-update event each time a step finishes, and a terminal event when it ends. You read them in order.
A run can stop to ask you a structured question — a choice, a yes or no, free text, or a request to connect a credential. You answer, and the run continues. This is called human-in-the-loop.
Each event arrives as a small JSON object with a `type` field that tells you what it is. A run typically streams a `metadata` event, then a `node_update` event per step, and finishes with a `done` event. If a step needs your input, you get an `interrupt` (workflows) or a `user_input_request` (the AI Composer and Assistant), the stream stays open, and you respond to continue.
A `heartbeat` event arrives periodically during quiet stretches — for example while a run is paused waiting on you — so the connection stays open. You can ignore heartbeats; they carry no run data. For the full event taxonomy, see the [realtime overview](/realtime/overview).
When a run pauses for your input, it does not lose its place — its state is checkpointed. You answer the question and the run resumes from exactly where it stopped. Answering a pause never charges you a second time; a run is charged once.
You can also cancel a running or paused run. Cancellation is graceful: the current step finishes, then the run stops. For the precise pause-and-resume contract, see [human-in-the-loop resume](/realtime/hitl).
Run progress (SSE) and canvas collaboration (which keeps several editors in sync) are two **separate** realtime systems that travel over different channels. The [realtime and collaboration model](/concepts/realtime-model) keeps them straight — and notes which sync paths are live versus retired.
## Run a workflow from code
The same loop works programmatically. You authenticate, start a run, then open the stream and read events until a terminal one. Every request carries two headers: your API key as a bearer token, and the organization the request runs in.
```bash cURL
# 1. Start the run
curl -X POST https://api.modulex.dev/workflows/run \
-H "Authorization: Bearer mx_live_2f9c4a1b8e7d6c5a4b3f2e1d0c9b8a76" \
-H "X-Organization-ID: 8a1f3c2e-9b4d-4e7a-bc11-7d6e5f4a3b2c" \
-H "Content-Type: application/json" \
-d '{"workflow_id": "wf_3d8b9a1c-2e4f-4a6b-8c0d-1e2f3a4b5c6d", "input": {"topic": "weekly sales summary"}}'
# → {"status":"running","run_id":"6a7b...","thread_id":"550e...","chat_id":"..."}
# 2. Observe the run (SSE stream of events until a terminal one)
curl -N https://api.modulex.dev/workflows/listen/6a7b8c9d-0e1f-2a3b-4c5d-6e7f8a9b0c1d \
-H "Authorization: Bearer mx_live_2f9c4a1b8e7d6c5a4b3f2e1d0c9b8a76" \
-H "X-Organization-ID: 8a1f3c2e-9b4d-4e7a-bc11-7d6e5f4a3b2c"
```
```python Python
import asyncio
from modulex import Modulex
async def main():
async with Modulex(
api_key="mx_live_2f9c4a1b8e7d6c5a4b3f2e1d0c9b8a76",
organization_id="8a1f3c2e-9b4d-4e7a-bc11-7d6e5f4a3b2c",
) as client:
# 1. Start the run
run = await client.executions.run(
workflow_id="wf_3d8b9a1c-2e4f-4a6b-8c0d-1e2f3a4b5c6d",
input={"topic": "weekly sales summary"},
)
# 2. Observe the run, event by event
async with client.executions.listen(run.run_id) as stream:
async for event in stream:
print(event.event)
if event.is_terminal:
break
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_2f9c4a1b8e7d6c5a4b3f2e1d0c9b8a76",
organizationId: "8a1f3c2e-9b4d-4e7a-bc11-7d6e5f4a3b2c",
});
// 1. Start the run
const run = await client.executions.run({
workflowId: "wf_3d8b9a1c-2e4f-4a6b-8c0d-1e2f3a4b5c6d",
input: { topic: "weekly sales summary" },
});
// 2. Observe the run, event by event
for await (const event of client.executions.listen(run.runId)) {
console.log(event.type);
if (event.type === "done" || event.type === "error" || event.type === "cancelled") {
break;
}
}
```
Wire fields stay snake_case (`run_id`, `thread_id`). The SDKs accept camelCase in your code and convert it for you on the request. For the full run-from-code walkthrough, see [Run a workflow (REST + SDK)](/guides/run-a-workflow); for authentication, see [Authentication](/api-reference/authentication).
## The shortcut: the Assistant
Not every task is worth building a workflow for. The [Assistant](/concepts/assistant) is an agentic chat that authors, runs, and observes in a single conversation: you state a goal, it decides which connected tools to call, it calls them step by step, and you watch the same kind of live stream. It pauses for your approval before sensitive actions, just like a run can.
Use the **AI Composer** when you want a reusable workflow you can run again and again. It produces a graph you own and can edit.
Use the **Assistant** for one-off or open-ended tasks. It acts directly with your tools — no workflow to set up first.
## Where everything lives
The whole loop happens inside an **organization** — the shared workspace and billing boundary. Your workflows, credentials, knowledge bases, plan, and credits all belong to one organization, and every run is metered against it. Each member has a **role**; the live roles are **owner** and **admin**, and actions such as using the AI Composer, the Assistant, and schedules require one of them.
How tenancy works: the organization context, membership, and what owners and admins can do.
How managed usage is metered in credits, and where the admission check applies.
## Keep going
A closer look at what a workflow is, what a run is, and the run identities you will meet.
How runs stream over SSE and how the canvas stays in sync across collaborators.
Create an organization, get an API key, and make your first authenticated call.
---
# Realtime & collaboration model
URL: https://docs.modulex.dev/concepts/realtime-model
ModuleX has two separate realtime systems: runs stream their progress to you over SSE, and the workflow canvas syncs between teammates over Socket.io. This page explains what each one is for and how they fit together.
ModuleX feels live in two different ways. When you run a workflow, you watch each step report its progress in real time. When you build a workflow with a teammate, you see their cursor move and their edits appear on the same canvas as yours. These are two separate systems, and keeping them apart is the whole mental model.
This page gives you that model in plain terms: what each realtime system does, when each one is in play, and what to expect when several people work together. For the wire-level detail, follow the links into [Realtime overview & event taxonomy](/realtime/overview).
## Two realtime planes
Think of ModuleX as having two independent "live" channels that never overlap. One pushes a run's progress *to* you. The other keeps everyone's *canvas* in agreement.
A one-way feed of a run's progress: the workflow, the AI Composer, or the Assistant reports each step to you as it happens.
A two-way sync of the workflow canvas: cursors, presence, locks, and edits flow between everyone in the same workflow.
"Realtime" in ModuleX always means one of these two systems. They share no events and no connection. A run streaming to you over SSE is unrelated to your teammate editing the canvas over Socket.io — even when both are happening in the same workflow at the same time.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1170 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** A diagram contrasting the two realtime planes side by side.
**[IMAGE_DETAILS]:** One illustration (not a screenshot), 16:9, light theme, ModuleX brand palette. Split the canvas into two labeled panels. Left panel "Run streaming (SSE)": a single server icon with a one-way arrow pointing right to one person icon, annotated "progress events, server → you". Show small example chips along the arrow reading "started", "step finished", "done". Right panel "Canvas collaboration (Socket.io)": two person icons connected by double-headed arrows to a shared canvas card in the middle, annotated "cursors, edits, locks — everyone ↔ everyone". A thin vertical divider between panels with the caption "Two separate systems". Keep text minimal inside shapes.
## Run streaming: watching a run as it happens
When you start a run, ModuleX opens a live feed of that run's progress over **Server-Sent Events (SSE)**. It is a one-way stream: the server sends you events as the run moves forward, and you watch.
You see this feed in three places, and they all work the same way:
Each node reports when it starts, when it finishes, and what it produced — until the run reaches `done`.
The Composer streams its thinking and the changes it makes to your canvas as it builds.
The Assistant streams its response and the tool calls it makes, step by step.
A run's stream carries a small set of progress events. You do not need to memorize them, but it helps to recognize the rhythm:
The first event describes the run: which workflow, which version, and the run's identifier.
As the run progresses, you get an event when a node (or an Assistant tool call) starts, and another when it produces output. If a step fails, you see the failure and any automatic retry.
The stream ends with a final event — `done` when the run completes, or `error` if it could not. A run you cancel ends with `cancelled` instead.
The stream is one-way. To act on a run — to cancel it, or to answer a question it asks — you make a separate request; you do not "reply" on the stream. See [SSE run streaming](/realtime/sse-streaming) for the full event list and frame format, and [Human-in-the-loop (HITL) resume](/realtime/hitl) for how a paused run is answered.
### When a run pauses to ask you something
Some runs stop and wait for a person. A workflow can include an [interrupt step](/workflow-builder/nodes/interrupt), and the [AI Composer](/concepts/ai-composer) and [Assistant](/concepts/assistant) can pause to ask for a choice, a confirmation, or a credential before continuing. This is **human-in-the-loop (HITL)**.
When this happens, the stream goes quiet — it does not end. The run is waiting. You answer the question (in the app, or with a separate request via an [SDK](/sdks/streaming-hitl)), and the run continues. Because answering restarts the run's progress, you reconnect to a fresh stream to watch the rest.
A paused run holds its place for a while, then expires if no one answers. The exact pause-and-resume mechanics — what kinds of questions a run can ask, and how each is answered — are covered in [Human-in-the-loop (HITL) resume](/realtime/hitl).
## Canvas collaboration: building together live
The second realtime system is for the [workflow builder](/workflow-builder/realtime-coediting). When two or more people open the same workflow, ModuleX connects them over **Socket.io** so the canvas stays in sync. Unlike run streaming, this is a two-way conversation: every person both sends their changes and receives everyone else's.
You see who else is in the workflow, each with their own color, and their live cursor as they move around the canvas.
When someone is editing a node, it is locked to them so two people cannot overwrite the same node at once.
Adding, moving, connecting, or deleting nodes is broadcast to everyone in the workflow as it happens.
Each accepted edit advances a version so the server can keep everyone consistent and resolve conflicts.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1171 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** Two people co-editing the same workflow canvas in real time.
**[APP_VIDEO_DETAILS]:** Screen recording from the live ModuleX app, ~30–45s, light theme, 16:9, shown as a split or picture-in-picture of two users. Show both users opening the same workflow; each sees the other's labeled, colored cursor moving. One user adds and connects a node and it appears instantly for the other. One user clicks into a node to edit it; show the other user seeing that node locked (an indicator that it is being edited by a teammate). Redact real names and organization names. Annotate the lock indicator with a callout "Locked while a teammate edits".
### Who can edit
Collaboration follows the same roles as the rest of ModuleX. Anyone in the [organization](/concepts/organizations-roles) can open a workflow and watch, but editing the canvas requires an **owner or admin**.
There is **no member role** in ModuleX. A `member` role existed in earlier versions and was retired on 2026-06-20. The live roles are **owner** and **admin** only, and editing the canvas — adding, moving, connecting, or locking nodes — is restricted to those roles. See [Roles & permissions](/security/roles-permissions) for the full map.
### Conflicts are handled for you
When several people edit quickly, two changes can arrive based on slightly different versions of the canvas. ModuleX detects this and asks the affected client to rebase onto the latest version, rather than letting one person silently overwrite another. You do not manage this by hand; the builder keeps everyone converged. The version, lock, and conflict details are in [Presence, locks & versioning](/realtime/presence-locks).
## External sync: when a workflow changes outside the canvas
Not every change to a workflow comes from a person dragging nodes. The [AI Composer](/concepts/ai-composer) edits the workflow on your behalf, and a workflow can also be changed through the API. ModuleX needs everyone with the canvas open to see those changes too.
This is **external sync**. When a workflow is edited from outside the live canvas, that change is delivered to everyone currently viewing the workflow over the same Socket.io collaboration system, using the **`workflow:external-sync`** event. The canvas updates in place, just as it would for a teammate's edit.
External sync runs over the live **Socket.io `workflow:external-sync`** event — not over a background channel. An older design that bridged external changes through a flat Redis channel named `workflow:updated` is **not the live path**: the backend does not publish to that channel, so it never fires. If you read about a `workflow:updated` Redis bridge anywhere, treat it as legacy; the path that actually keeps the canvas in sync is `workflow:external-sync`. The event reference is [Socket.io collaboration events](/realtime/socket-events), and the broader gaps are tracked in [Known limitations](/reference/known-limitations).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1172 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** The AI Composer editing a workflow while a teammate watches the canvas update.
**[APP_VIDEO_DETAILS]:** Screen recording from the live ModuleX app, ~20–30s, light theme, 16:9. Show user A asking the AI Composer to make a change (for example, "add a step that sends a Slack message"). As the Composer applies the change, show user B's canvas — open to the same workflow — updating in place to show the new node without user B doing anything. Redact real names and organization names. Annotate user B's canvas with a callout "Updated by external sync".
## Putting it together
The two systems often run at once, and that is fine — they do not interfere.
You and a teammate are both in the same workflow. Your teammate adds a node; you see it appear over **canvas collaboration**. Meanwhile you run the workflow; you watch its steps complete over **run streaming**. Two live systems, two purposes, no conflict.
You ask the [AI Composer](/concepts/ai-composer) to restructure the workflow. The Composer streams its progress to you over **run streaming**, and the edits it makes land on everyone else's canvas over **external sync** on the collaboration system.
A run reaches a [human-in-the-loop](/realtime/hitl) step. Its **run stream** goes quiet while it waits. You answer, and a fresh stream picks up where it left off. The canvas, and anyone editing it, is unaffected.
## Where to go next
The technical map of both planes — every SSE event and every Socket.io event in one place.
Invite a teammate and co-edit a workflow live, step by step.
What co-editing looks like in the app: presence, cursors, and live edits.
How canvas edits and external changes sync, in the builder's own terms.
---
# Workflow engine & nodes
URL: https://docs.modulex.dev/concepts/workflow-engine
How the ModuleX workflow engine compiles a JSON workflow into a runnable graph: the 9 node types, edges, the __start__/__end__ virtual nodes, run state and reducers, and the {{nodeId.path}} reference model.
{/* AUDIENCE: technical. Feeds: B04 (workflow-engine), X04 (data-model), X09 (glossary). */}
The workflow engine is the runtime that turns a `WorkflowDefinition` — the JSON contract you build in the [workflow builder](/workflow-builder/overview) or generate with the [AI Composer](/concepts/ai-composer) — into an executable graph and runs it. This page documents the engine's contract: how a workflow compiles, the 9 node types and what each writes to state, how edges and the virtual `__start__`/`__end__` endpoints work, how run state and reducers behave, and how the `{{nodeId.path}}` reference syntax resolves data between steps.
This is the conceptual model behind every run. For the per-node configuration reference, see the individual [node type pages](/workflow-builder/nodes/overview). For the wire-level run lifecycle and events, see [SSE run streaming](/realtime/sse-streaming).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1100 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** Diagram of how a JSON workflow definition compiles into a runnable graph.
**[IMAGE_DETAILS]:** Show the pipeline left to right: a `WorkflowDefinition` JSON block (metadata, config, state_schema, nodes[], edges[]) → a compile step that builds dynamic run state (one field per node id) and wires nodes/edges → the compiled graph with `__start__` and `__end__` rendered as dashed virtual endpoints feeding into and out of real nodes → a "run" arrow streaming node events out over SSE. Annotate that the checkpointer persists state to Postgres. 16:9, light and dark variants, no decorative gradients.
## The mental model
A workflow is a directed graph of **nodes** connected by **edges**, executed over a shared **run state**. The engine evaluates the graph one node at a time (or in parallel where a loop fans out), and every node writes its result back into state. Later nodes read earlier results through the `{{nodeId.path}}` reference syntax.
Four pieces make up the contract:
The 9 step types — `llm`, `tool`, `agent`, `function`, `conditional`, `interrupt`, `transformer`, `guardrails`, `knowledge`. Each node writes its result to run state under its own `id`.
Directed connections between nodes. The virtual `__start__` and `__end__` endpoints mark where execution enters and leaves the graph.
A dynamic dictionary that flows through the run. Its fields come from your `state_schema`, plus one auto-added field per node id, plus any loop fields.
The `{{nodeId.path}}` syntax that pulls a value out of state — typed when the whole field is a single reference, templated when embedded in a string.
Under the hood, the engine compiles your `WorkflowDefinition` into a LangGraph `StateGraph`, runs it in a background task, persists state to Postgres through LangGraph's `AsyncPostgresSaver` checkpointer, and streams node and run events over [SSE](/realtime/sse-streaming). You do not interact with LangGraph directly — you describe the graph in JSON and the engine handles compilation, persistence, and streaming.
## The `WorkflowDefinition`
A workflow is a single JSON object. These are its top-level fields.
Workflow name, description, version, and tags. The engine denormalizes some of these for fast filtering, but the workflow definition is the source of truth.
Execution configuration. Several fields are accepted on the wire but **forced to constant values** by the engine regardless of what you send (see [Execution config](#execution-config) below).
Declares the named fields that flow through the run, their types, and their reducers. See [Run state](#run-state).
The list of `NodeDefinition` objects. **The virtual `__start__` and `__end__` endpoints must not appear here** — they are wired automatically and a validator rejects a definition that lists them as nodes.
The list of `EdgeDefinition` objects connecting nodes. Edges may also express conditional branches and loops.
The node where execution begins. Defaults to the virtual `__start__` endpoint.
The canvas `{x, y}` of the `__start__` endpoint. Visual only — it has no effect on execution.
The definition is parsed with extra fields ignored, so removed or unknown top-level keys (for example, a legacy `end_points` field) are silently dropped rather than causing an error. Build against the fields documented here.
### Execution config
`config` accepts the fields below, but the engine **overrides** most of them with fixed values. You can send them, but only `recursion_limit` is honored from your input.
| Field | Wire default | Effective value | Notes |
| --- | --- | --- | --- |
| `recursion_limit` | `500` | respected | The maximum number of node transitions in one run. The default of 500 supports loops up to roughly 100 iterations (each node transition counts as one step). |
| `enable_checkpointing` | `true` | always `true` | State is always persisted; you cannot disable it. |
| `checkpointer_type` | `"postgres"` | always `"postgres"` | The checkpointer is always Postgres-backed. See [Checkpointer and threads](#checkpointer-and-threads). |
| `stream_mode` | `"updates"` | always `"updates"` | The engine streams per-node updates as they complete. |
| `enable_subgraph_streaming` | `true` | always `true` | Subgraph events stream through to the client. |
A run can override `recursion_limit` at execution time through its `ExecutionConfig` (`thread_id?`, `recursion_limit?`, `checkpoint_id?`); otherwise the workflow's configured limit applies.
## Nodes
A workflow has exactly **9 node types**. Every node, whatever its type, follows the same output convention: **it writes its result to run state under its own `id`**. A node with `id: "node_llm_1"` produces `state["node_llm_1"]`, and later nodes reference it as `{{node_llm_1}}`.
Several configs expose a legacy `output_key` field. It is **deprecated** — node output always lands under the node `id`, not a custom key. Do not rely on `output_key`, `input_keys`, or `prompt_template`; they are kept only for backward compatibility.
Each node type maps to one configuration object on the `NodeDefinition`. The full per-node parameter reference lives on the dedicated node pages; the table below is the index.
| Type | Config slot | What it does | Reference |
| --- | --- | --- | --- |
| `llm` | `llm_config` | Calls a language model with system/user prompts, optional structured output. | [LLM node](/workflow-builder/nodes/llm) |
| `tool` | `tool_config` | Calls a single integration tool (action). | [Tool node](/workflow-builder/nodes/tool) |
| `agent` | `agent_config` | Runs an autonomous tool-calling loop up to `max_iterations`. | [Agent node](/workflow-builder/nodes/agent) |
| `function` | `function_config` | Runs a built-in registry function (HTTP, webhook, schema validation). | [Function node](/workflow-builder/nodes/function) |
| `conditional` | `conditional_config` | Branches on an expression or LLM decision, or controls a loop. | [Conditional node](/workflow-builder/nodes/conditional) |
| `interrupt` | `interrupt_config` | Pauses the run to ask a human a structured question. | [Interrupt node](/workflow-builder/nodes/interrupt) |
| `transformer` | `transformer_config` | Reshapes and combines data between steps. | [Transformer node](/workflow-builder/nodes/transformer) |
| `guardrails` | `guardrails_config` | Validates content with JSON/regex/PII checks. | [Guardrails node](/workflow-builder/nodes/guardrails) |
| `knowledge` | `knowledge_config` | Retrieves from a knowledge base. | [Knowledge node](/workflow-builder/nodes/knowledge) |
An unknown `type` fails compilation with an "Unsupported node type" error. See the [node types overview](/workflow-builder/nodes/overview) for the complete list and how each writes to state.
### The `NodeDefinition`
Every node, regardless of type, shares this shape.
The node's unique identifier within the workflow. This is the key its output is written under in run state, and the name later nodes reference with `{{id}}`.
One of the 9 node types.
A human-readable label shown in the builder.
An optional description of what the node does.
Whether the node participates in the run. A disabled node is dropped at compile time and its edges are rewired to the next enabled target, so you can disable a step without rewiring the graph by hand. A `null` value is treated as `true`.
The node's horizontal canvas position. Visual only.
The node's vertical canvas position. Visual only.
Optional per-node retry policy. Most node types are retry-wrapped; the `interrupt` node is **not** retry-wrapped, because retrying a human pause is meaningless.
Exactly one type-specific configuration slot, matching the node `type` (for example, `llm_config` for an `llm` node). The builder may send a wrapped `{"config": {...}}` form; the engine normalizes it to the type-specific key automatically.
### What each node type writes to state
Because every node writes under its own `id`, knowing each type's output shape tells you exactly what later nodes can reference.
Resolves the system and user prompt templates, calls the model, and returns the response text under the node id. If you configure a `structured_output_schema`, the engine asks the model for structured JSON and returns the parsed object instead, falling back to JSON extraction from the raw response if structured output fails. LLM usage is metered in [credits](/billing/credits) after each call. See the [LLM node](/workflow-builder/nodes/llm).
Resolves the `input_mapping` (which uses `{{...}}` references), loads the tool for the configured integration and credential, invokes it, and returns the unwrapped result under the node id. A `{success, action, result: {...}}` wrapper is flattened to the root, with `result` kept for backward-compatible `.result.field` paths. The tool node honors both `parameter_defaults` and `parameter_overrides`. See the [Tool node](/workflow-builder/nodes/tool).
Binds the configured tools to the model and runs a tool-calling loop up to `max_iterations` (default 10): each turn invokes the model, executes any tool calls, and appends the results. The agent applies `parameter_defaults` only — `parameter_overrides` are **ignored** for agents. It raises if the resolved input is empty, and meters LLM usage every iteration. See the [Agent node](/workflow-builder/nodes/agent).
Looks up a built-in function by `function_name` and executes it. On success it writes `result.data` under the node id; on failure it writes `{error, success: false, ...}` so downstream nodes can branch on the error. There are exactly four built-ins: `http_request`, `send_webhook`, `validate_schema`, and `validate_workflow_schema`. See the [Function node](/workflow-builder/nodes/function).
Has a `condition_type` of `"expression"`, `"llm"`, or `"loop"`. An expression node evaluates ordered branches and stores the matched target; the engine then adds conditional edges that route on it. An LLM node asks the model to pick a route. A loop node acts as the loop controller. See the [Conditional node](/workflow-builder/nodes/conditional).
Builds a question payload (`message`, `data`, optional `resume_schema` and `examples`) and pauses the run. The active client receives an `interrupt` event; the run status becomes `interrupted`. On [resume](/realtime/hitl), the human's value is stored under the node id. This node is **not** retry-wrapped. See the [Interrupt node](/workflow-builder/nodes/interrupt).
Resolves a `source` reference and applies an ordered list of operations (string, object, array, type, date, and math operations). The transformed value is written under the node id. See the [Transformer node](/workflow-builder/nodes/transformer).
Runs JSON-schema, regex, and PII checks against a `source` reference, with an `on_failure` action of `block`, `warn`, `transform`, or `route`. The hallucination check is a placeholder and returns a "coming soon" marker. The result records which validations ran, whether the content was valid, and any findings. See the [Guardrails node](/workflow-builder/nodes/guardrails).
Resolves a `query` reference and retrieves from the configured [knowledge base](/concepts/knowledge-rag). Managed (`modulexdb`) retrieval reserves and records [credits](/billing/credits); bring-your-own-key vector stores are uncosted. The output is formatted as `chunks`, `context`, or `both`. See the [Knowledge node](/workflow-builder/nodes/knowledge).
## Edges and the virtual endpoints
Edges are directed connections between nodes. Two endpoint names are **virtual**: `__start__` and `__end__`. They mark where execution enters and leaves the graph but are not real nodes — they have no configuration and **must not appear in the `nodes` array**.
```json title="Edges with the virtual endpoints"
{
"edges": [
{ "source": "__start__", "target": "node_llm_1" },
{ "source": "node_llm_1", "target": "node_http_2" },
{ "source": "node_http_2", "target": "__end__" }
]
}
```
A few rules govern how edges compile:
An edge from `__start__` connects the engine's entry point to your first node. The workflow's `entry_point` defaults to `__start__`.
An edge to `__end__` terminates a branch.
Any enabled node that has no outgoing edge is automatically connected to the exit. **An explicit edge to `__end__` is therefore optional** — leave it out and the node still terminates correctly.
A node with `enabled: false` is dropped at compile time and its edges are rewired to the next enabled target, recursively.
A node with more than one incoming edge is wrapped so it runs once after its predecessors converge, rather than once per incoming edge.
Listing `__start__` or `__end__` in the `nodes` array is rejected by the workflow validator as a virtual-node error. They belong only in `edges` and in `entry_point`.
## Run state
State is a single dictionary that flows through the run. Its fields come from three sources, combined at compile time:
1. **Your declared fields** — the `state_schema.fields` you define.
2. **One field per node id** — the engine auto-adds a field (typed `Any`) for every node so its output streams correctly. This is why `{{node_id}}` always resolves to that node's output.
3. **Loop fields** — auto-added bookkeeping fields for any loop (see [Loops](#loops)).
### Declaring a state field
Each entry in `state_schema.fields` is a `StateField`.
One of `string`, `integer`, `float`, `boolean`, `object`, `array`, or `messages` (mapped to Python `str`, `int`, `float`, `bool`, `dict`, `list`, and `list` respectively).
An optional description of the field.
How concurrent or repeated writes to this field merge. One of `none`, `add`, or `update` (see [Reducers](#reducers)).
Whether the field must be present.
The value applied at run start if no input overrides it.
At run start, the engine applies declared `default`s first, then type-appropriate empty values for anything without a default, then your run `input` on top — so input always wins.
### Reducers
A reducer decides what happens when a field is written more than once (for example, by parallel branches of a loop).
Plain replace — the new value overwrites the old. This is the default.
A smart-append reducer. For `array` fields it appends, auto-wrapping a scalar into a single-element list (`[] + "x"` becomes `["x"]`); for other types it uses addition. Use this to accumulate results across loop iterations.
A type-safe dictionary merge. New keys are added and existing keys are overwritten, while the rest of the object is preserved.
The reducer matters most inside loops and parallel branches, where the same field is written multiple times. For a straight-line workflow, the default `none` (replace) is usually what you want. See [Variables & references](/workflow-builder/variables-and-references) for worked examples.
## References — `{{nodeId.path}}`
References are how data moves between nodes. The syntax is `{{nodeId.path}}`, where `nodeId` is a node's `id` and `path` is an optional dot-and-bracket path into that node's output.
```text title="Reference forms"
{{node_abc123}} whole output of node_abc123
{{node_search.results[0].title}} nested field via dot + bracket path
{{node_http_2.body.status}} field of a structured result
```
How a reference resolves depends on where it appears:
When a field is **exactly** one `{{...}}` reference, the engine returns the **native typed value** — a number stays a number, an object stays an object, an array stays an array. Use this to pass structured data between nodes without stringifying it.
```json title="Typed pass-through"
{
"input_mapping": {
"results": "{{node_search.results}}"
}
}
```
When a `{{...}}` reference is **embedded in a larger string**, the engine substitutes it as text. Object and array values are JSON-encoded into the string. Unresolved references are left intact rather than blanked out.
```json title="String interpolation"
{
"user_prompt": "Summarize this article: {{node_fetch.body}}"
}
```
A **list item** of the form `{{...nodeId.path}}` (note the leading `...`) is spliced into the surrounding list when it resolves to a list; a scalar or object is appended, and `None` contributes nothing. The `...` prefix only has spread meaning in a list-item position.
```json title="Spreading a list into a list"
{
"items": ["{{...node_a.rows}}", "{{...node_b.rows}}", "literal"]
}
```
Resolution rules to keep in mind:
- **Missing paths resolve to nothing.** An out-of-range index, a missing key, or a malformed bracket path resolves to `null` silently rather than raising — design downstream nodes to tolerate `null`.
- **`input_mapping` skips empty values.** Keys whose resolved value is `null` or an empty string are dropped from the mapping, so they never reach the tool or function.
- **Mixed and nested structures recurse.** A reference inside a nested object or list is resolved per-item, preserving the surrounding structure.
See [Variables & references](/workflow-builder/variables-and-references) for the full reference cookbook.
## Loops
A loop repeats a section of the graph. Loops are expressed either as an edge whose condition type is `loop`, or as a `conditional` node whose `condition_type` is `"loop"` (the node acts as the loop controller). A loop has three modes:
A fixed number of iterations, from `iterations` or a `iterations_ref` reference.
One iteration per item in a `collection` (a `{{...}}` reference). Set `parallel: true` to fan the iterations out concurrently; otherwise they run in sequence.
Repeats while a condition expression is true, bounded by `max_iterations` (default 100) as a safety stop.
Every loop auto-creates bookkeeping fields in run state, keyed by its `loop_id`:
| Field | Type | Present for | Meaning |
| --- | --- | --- | --- |
| `{loop_id}_iteration` | integer | all loops | The current iteration count. |
| `{loop_id}_initialized` | boolean | all loops | Whether the loop has started. |
| `{loop_id}_completed` | boolean | all loops | Whether the loop has finished. |
| `{loop_id}_item` | any | foreach | The current item. |
| `{loop_id}_index` | integer | foreach | The current item's index. |
| `{loop_id}_collection_size` | integer | foreach | The total number of items. |
| `{loop_id}_results` | array | when `accumulate` is on | Accumulated per-iteration results (uses the smart-append reducer). |
A loop's `exit_target` defaults to `__end__` — an empty or missing exit target is normalized to the virtual end. Set `body_target` to the first node of the loop body, and optionally `body_end` (it defaults to `body_target`) to mark where one iteration ends.
`recursion_limit` (default 500) caps total node transitions across the whole run, including every loop iteration. A long-running `foreach` over a large collection can exhaust it — raise the limit on `config` or at run time, or set `parallel: true` to fan out instead of iterating.
## Checkpointer and threads
Every run's state is persisted by LangGraph's `AsyncPostgresSaver` checkpointer, backed by the same Postgres database as the rest of ModuleX. Checkpointing is always on — the `enable_checkpointing` and `checkpointer_type` config fields are forced, so you cannot turn it off or switch to an in-memory saver.
The checkpointer is what makes [human-in-the-loop](/realtime/hitl) possible: when an `interrupt` node pauses a run, its full state is checkpointed, and a resume call restores that state and continues the **same** run from where it stopped.
A **thread** is the unit of checkpoint continuity, identified by a `thread_id` on the run config. When you run a workflow from a chat, the chat's id is reused as the thread id, so the run shares the conversation's checkpoint thread; an ephemeral run without a thread gets a generated id.
## Run lifecycle and events
A run executes in a background task: it persists a durable run row, streams a `metadata` event, applies state defaults, then steps the graph node by node, publishing a `node_update` event as each node completes. An `interrupt` pauses the run; `done`, `error`, or `cancelled` terminate it. A run has a default timeout of one hour.
You observe a run by listening to its [SSE stream](/realtime/sse-streaming). The wire is a sequence of `data: \n\n` frames with **no `event:` line** — the event discriminator is the `type` key inside each JSON payload, so a client parses each frame and switches on `.type`.
```text title="SSE frames for a successful two-node run"
data: {"type": "metadata", "data": {"run_id": "run_7f3a", "thread_id": "chat_42", "workflow_name": "My Flow", "workflow_version": 3, "workflow_type": "workflow"}}
data: {"type": "node_update", "node": "node_llm_1", "output": {"node_llm_1": "Hello world"}}
data: {"type": "node_update", "node": "node_http_2", "output": {"node_http_2": {"status_code": 200, "body": {"ok": true}}}}
data: {"type": "done", "data": {"message": "Workflow completed successfully"}}
```
Note that the live wire is **flat** — `node_update` carries `node` and `output` keys, not the `node_id`/`status` fields of the internal typed model. Build clients against the wire shape shown here. A `{"type": "heartbeat"}` keepalive is injected every 15 seconds so the connection never idles closed, and on reconnect the stream replays the run's buffered history before tailing live. The full event taxonomy, interrupt and resume frames, and reconnection semantics are documented on [SSE run streaming](/realtime/sse-streaming); for workflow concepts and the distinct run-id identities, see [Workflows & runs](/concepts/workflows-and-runs).
### Failures and credits
There is no fixed per-node credit charge. Charging happens inline: LLM and agent calls meter token usage, and managed knowledge retrieval reserves and records [credits](/billing/credits) per call. A mid-run hard stop — for example, exhausted credits — surfaces as a node error carrying a machine-readable reason code, so a client can match it deterministically. The managed-knowledge billing gate is best-effort inside a run: a billing hiccup is recorded but does not crash a workflow that is already running.
For node-level retry behavior, how failures surface in the stream, and debugging failed runs, see [Error handling & retries](/workflow-builder/error-handling-retries). For where and how managed usage is gated, see [Usage gating & limits](/billing/usage-gating).
## Next steps
Every node type with its full parameter reference.
The complete `{{nodeId.path}}` reference and run-state cookbook.
What a run is, its status model, and the three run-id identities.
The full run-event taxonomy and how to consume it.
---
# Workflows & runs explained
URL: https://docs.modulex.dev/concepts/workflows-and-runs
Understand the difference between a workflow and a run in ModuleX, how a run moves through its lifecycle and status, and the three distinct identifiers that all get called a run id.
A **workflow** is the thing you build once. A **run** is what happens each time you press go. Keeping those two ideas separate is the key to understanding everything else on this page — including the three different identifiers that are all, confusingly, called a "run id".
The reusable design: the nodes, the connections between them, and the settings you saved. It sits still until you run it.
One execution of that design with specific inputs. Each run has its own progress, its own result, and its own identifier.
## Workflow vs. run
Think of a workflow like a recipe and a run like the meal you cook from it. One recipe, many meals — each meal made with different ingredients and turning out slightly differently.
You edit it in the [workflow builder](/workflow-builder/overview) or with the [AI Composer](/concepts/ai-composer), give it a name, and [deploy](/workflow-builder/execution/deploy) it. It stays put until you change it.
Starting a run takes a snapshot, feeds in your inputs, and executes the [nodes](/workflow-builder/nodes/overview) step by step. When it finishes, the run becomes a record in your history.
Every time you run from the canvas, [from chat](/workflow-builder/execution/run-on-chat), [from the API](/workflow-builder/execution/api-endpoint), or [on a schedule](/workflow-builder/execution/schedule), you create a new, independent run.
If you delete a workflow, its past runs stay in your history so you keep the audit trail. The run record keeps everything except its link back to the (now deleted) workflow.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1090 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** A simple "one workflow, many runs" diagram.
**[IMAGE_DETAILS]:** Left side: a single labelled workflow card ("Research summary"). An arrow fans out to the right into three run cards, each with a different input ("AI trends", "Q2 sales", "competitor news") and a different status pill (succeeded / running / failed). Light theme, clean and friendly, 16:9, minimal text so it reads at a glance.
## What happens during a run
Once you start a run, ModuleX walks through the workflow's nodes in order, passing data from each step to the next. You can watch this happen live, and some workflows pause partway through to ask you something before they continue.
You provide the inputs and press run. ModuleX checks your plan's [credits and limits](/concepts/credits-billing) first, then begins executing in the background and immediately hands you a **run id** so you can follow along.
Each node runs and writes its result into the run's shared state. Progress streams to you live over [Server-Sent Events](/realtime/sse-streaming), so you see each step as it completes rather than waiting for the whole thing.
If the workflow includes an [interrupt node](/workflow-builder/nodes/interrupt), the run pauses and asks a question — for example, to approve a draft before it is sent. The run waits for your answer; nothing idles out.
You respond, and the run continues from exactly where it stopped. It keeps the same run id and is never charged twice for the same execution.
The run ends in one of a few final states (done, failed, or cancelled) and is saved to your run history, where you can reopen it later to see its inputs and results.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1091 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** A 30–45s screen recording of a run streaming live in the app, including an interrupt pause and resume.
**[APP_VIDEO_DETAILS]:** Record in the workflow builder. Start a run, show nodes lighting up one by one as the live stream arrives, pause on an interrupt prompt ("Approve this plan?"), click approve, then show the run completing with a success state. Highlight the run-id chip in the runs panel. Light theme, 16:9, no audio narration needed (captions optional).
## The run lifecycle
A run moves through a predictable set of moves: start it, watch it, optionally inspect or steer it, and let it finish. You rarely think about these as separate actions in the app — but they map directly to what happens behind the scenes and to the [API](/workflow-builder/execution/api-endpoint).
Kick off a run from a deployed workflow, an ad-hoc canvas, or a schedule. ModuleX returns right away with a run id while the work continues in the background.
Subscribe to the run's live event stream to follow progress in real time. Reconnecting mid-run replays what you missed, so you never lose the thread. See [SSE run streaming](/realtime/sse-streaming).
When a run pauses at an interrupt, send your answer to continue it. The run picks up from its saved checkpoint — same run, same id.
Stop a run that is running or paused. Cancellation is graceful: the current step finishes, then the run stops cleanly between steps.
## The status model
Every run carries a status that tells you where it is. The live stream you watch and the saved history record use slightly different words for the same idea, which is worth knowing so nothing surprises you.
| Status | What it means |
| --- | --- |
| `pending` | The run is queued and about to start. |
| `running` | The run is actively executing its nodes. |
| `interrupted` | The run is paused at an interrupt node, waiting for your answer. |
| `succeeded` | The run completed successfully. |
| `failed` | A step errored and the run stopped. |
| `cancelled` | You (or a teammate) stopped the run. |
| `skipped` | The run did not execute (for example, a scheduled run that was skipped). |
**One word, two places.** While a run streams live, a successful finish arrives as a `done` event. In your saved run history, that same run is recorded with the status `succeeded`. They describe the same outcome — `done` is the live signal, `succeeded` is the stored label.
## The three identifiers all called a "run id"
This is the single most important thing to get right about runs. ModuleX uses the phrase "run id" for **three different identifiers** that serve different jobs. They are not interchangeable, and using one where another is expected leads to a "not found" result.
Reach for the right id for the job: use the **execution run id** to watch, resume, or cancel a live run; use the **run record id** to open a finished run in your history; and the **scheduled-run id** only when you are looking at a schedule's own run log.
The live handle for one execution. It is what you watch, resume, and cancel against while a run is in flight.
The permanent key for a finished run in your history. You use it to look a completed run back up later.
The key for one entry in a schedule's own run log. It is separate from both ids above.
This is the identifier ModuleX hands back the instant you start a run. It is what every live action keys off:
- **Watch** the run's live stream (`/workflows/listen/{run_id}`).
- **Cancel** a run that is still going (`/workflows/cancel/{run_id}`).
- It is also used to replay a run's recent event history if you reconnect.
For a workflow run, **resuming after an interrupt keeps the same execution run id** — one logical run, charged once. For the conversational [AI Composer](/concepts/ai-composer) and [Assistant](/concepts/assistant), each turn (and each resume) gets a **new** execution run id, even though the conversation itself keeps one stable thread. So an execution run id is not a stable handle across a whole conversation.
Every real run is also written to your durable run history as its own record, and that record has its own identifier — separate from the execution run id above.
You use the **run record id** to open a single finished run and read back its inputs and results (`/workflow-runs/{run_pk}`). When you list your run history, each row shows *both* ids: the execution run id (the live handle the run used) and the record id (the history key). Pass the record id — not the execution run id — when you fetch one run's detail.
When a workflow runs [on a schedule](/workflow-builder/execution/schedule), the schedule keeps its **own** log of each time it fired. Every entry in that log has its own identifier, separate again from the two ids above.
A single scheduled-run entry links the schedule, the workflow it ran, and the execution run id of the actual run it triggered — so you can trace a schedule firing all the way back to the live run it produced. When you open one entry in a schedule's run history, you address it by its scheduled-run id, not by the execution run id it points to.
### Side by side
| Identifier | What it points to | When you use it |
| --- | --- | --- |
| **Execution run id** | One live execution | Watch, resume, or cancel a run in flight |
| **Run record id** | One row in your run history | Open a finished run to read its inputs and result |
| **Scheduled-run id** | One entry in a schedule's run log | Inspect a single scheduled firing |
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1092 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** A diagram showing the three "run id" identities and how they relate.
**[IMAGE_DETAILS]:** Three labelled boxes — "Execution run id (live)", "Run record id (history)", "Scheduled-run id (schedule log)". Draw an arrow from the scheduled-run entry to the execution run id ("triggers"), and an arrow from the execution to the run record ("saved as"). Annotate that resume keeps the same execution run id for workflows but mints a new one for chat agents. Light theme, friendly, 16:9; keep labels short.
## See it in practice
You do not need to think about these ids in the app — the interface hands you the right one for whatever you are doing. They become visible when you run a workflow programmatically. The example below starts a run (which returns the **execution run id**), then lists your run history (where each row carries both the **execution run id** and the **run record id**).
```bash cURL
# 1. Start a run — the response includes the execution run id ("run_id").
curl -X POST https://api.modulex.dev/workflows/run \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111" \
-H "Content-Type: application/json" \
-d '{"workflow_id":"550e8400-e29b-41d4-a716-446655440000","input":{"query":"AI trends"}}'
# 2. List run history — each row carries both the execution run id ("run_id")
# and the run record id ("id").
curl https://api.modulex.dev/workflow-runs \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111"
```
```python Python
from modulex import Modulex
async with Modulex(
api_key="mx_live_xxx",
organization_id="11111111-1111-1111-1111-111111111111",
) as client:
# 1. Start a run — `run.run_id` is the execution run id.
run = await client.executions.run(
workflow_id="550e8400-e29b-41d4-a716-446655440000",
input={"query": "AI trends"},
)
# 2. List run history — each row has `run_id` (execution) and `id` (record).
history = await client.executions.list_runs()
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_xxx",
organizationId: "11111111-1111-1111-1111-111111111111",
});
// 1. Start a run — `run.run_id` is the execution run id.
const run = await client.executions.run({
workflowId: "550e8400-e29b-41d4-a716-446655440000",
input: { query: "AI trends" },
});
// 2. List run history — each row has `run_id` (execution) and `id` (record).
const history = await client.workflowRuns.list();
```
Every request uses `Authorization: Bearer mx_live_…` together with the `X-Organization-ID` header. See [authentication](/api-reference/authentication) for how to get a key and find your organization id.
## Where to go next
How nodes, edges, and run state actually fit together under the hood.
The live event stream you watch a run with, frame by frame.
A hands-on, end-to-end walkthrough across REST and both SDKs.
Run a workflow automatically on a recurring schedule.
---
# ModuleX Enterprise
URL: https://docs.modulex.dev/enterprise/branding
ModuleX Enterprise is the top tier of ModuleX — the same AI workflow orchestration platform, with self-hosting, SSO and SAML, custom limits, and dedicated support. Here is how the Enterprise edition is positioned and named, and how it differs from Free, Pro, and Max.
ModuleX Enterprise is the top tier of ModuleX. It is not a different product or a separate codebase — it is the same AI workflow orchestration platform you can use today, packaged for organizations that need to run it at scale, on their own terms, with self-hosting, single sign-on, custom limits, and dedicated support.
This page explains how the Enterprise edition is positioned, what makes it different from the other tiers, and how ModuleX is named and branded. For the business case and value, see [ModuleX for enterprise](/enterprise/overview). For the security and trust details behind it, see [Enterprise](/security/enterprise).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4310 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** A simple positioning graphic showing the four ModuleX tiers — Free, Pro, Max, Enterprise — as one continuous product, with Enterprise highlighted as the top tier rather than a separate product.
**[IMAGE_DETAILS]:** Authored illustration, not an app capture. Show one horizontal track labeled "ModuleX" with four stops (Free, Pro, Max, Enterprise) left to right; mark Enterprise as the endpoint and tag it with "self-hosting · SSO/SAML · custom limits · dedicated support." Use the ModuleX brand wordmark. 16:9, light theme, no numeric prices.
## What "ModuleX Enterprise" means
ModuleX is an AI workflow orchestration platform. You build AI workflows with natural language or a visual canvas, connect the tools you already use, and run those workflows from chat, the API, or the SDKs.
"Enterprise" is the top of the four tiers — **Free, Pro, Max, and Enterprise**. Calling it the "Enterprise edition" is shorthand for the same platform configured for larger teams: the capabilities that smaller teams do not need are switched on, and the numbers that smaller teams hit as limits become custom.
Workflows, the AI Composer, the Assistant, knowledge and RAG, integrations, and the SDKs are the same across every tier. Enterprise adds capabilities and removes ceilings — it does not change what ModuleX is.
The Enterprise tier is positioned "for organizations at scale" — teams that need to invite many people, run large-scale operations, and operate ModuleX under their own governance.
Free, Pro, and Max are self-serve. Enterprise is the one tier you arrange with the ModuleX team, because the limits, deployment, and support are tailored to you.
There is no separate "Enterprise" download, login, or product to learn. If you already know how to build and run a workflow in ModuleX, you already know ModuleX Enterprise. The difference is in deployment, scale, sign-on, and support — not in how the product works day to day.
## How Enterprise differs from the other tiers
Every tier shares the same core: workflows, the [AI Composer](/concepts/ai-composer), the [Assistant](/concepts/assistant), [knowledge and RAG](/concepts/knowledge-rag), the full integration catalog, and the JavaScript and Python SDKs. What changes at the Enterprise tier is who can run it where, how much it can do, and how you are supported.
Enterprise is the only tier that can be self-hosted. Free, Pro, and Max run on ModuleX's managed cloud; Enterprise can run inside your own environment. See [deployment and SSO](/enterprise/deployment-sso).
Single sign-on with SAML is an Enterprise-only capability, so your team signs in through your identity provider. Lower tiers do not include SSO or SAML.
Credits, run rates, API rate limits, and storage are fixed allowances on Free, Pro, and Max. On Enterprise they are custom — sized to your usage rather than capped at a tier number.
Lower tiers are supported through community and email channels. Enterprise adds dedicated support, including a dedicated Slack channel and hands-on onboarding.
### What the Enterprise tier includes
These are the capabilities ModuleX lists for the Enterprise tier:
- **Invite teammates** — bring your whole team into your [organization](/concepts/organizations-roles).
- **Large-scale operations** — run at volumes the fixed tiers cap.
- **Custom rate limits** — run-rate, API, and credit limits sized to you, not to a tier.
- **Advanced analytics** — deeper visibility into usage and activity.
- **Onboarding assistance** — hands-on help getting your team set up.
- **Dedicated Slack channel** — a direct line to the ModuleX team.
Beyond the plan card, the Enterprise capability set named for sales conversations is: **SSO and SAML**, **self-hosted deployment**, **custom rate limits and credits**, **advanced analytics and audit logs**, **dedicated Slack support**, and **hands-on onboarding**.
ModuleX lists audit logs across all tiers in its plan comparison, but a per-tier entitlement that gates audit logs could not be confirmed in the product configuration, so treat audit-log behavior as **TBD** until verified. For everything ModuleX could not yet confirm, see [known limitations](/reference/known-limitations).
### Tier-by-tier at a glance
The pricing details — including ModuleX's two conflicting annual figures, which are presented side by side and not yet resolved — live on [plans and pricing](/billing/plans). This page covers only what changes at the Enterprise tier.
Capability
Free, Pro, Max
Enterprise
**Self-hosted deployment**
Not available
Available
**SSO and SAML**
Not available
Available
**Credits, run rates, limits, storage**
Fixed per tier
Custom
**Pricing**
Published per tier
Custom — arranged with sales
**Support**
Community and email
Dedicated, with a Slack channel
**Onboarding**
Self-serve
Hands-on onboarding
**How you get it**
Sign up in the app
Contact sales
## Brand and naming
ModuleX is the name of the product and the brand. Using the name correctly matters most in two places: in your own documents and contracts, and when you refer to the company behind the product.
**ModuleX** is the product and brand name, written as one word with a capital M and a capital X. Use "ModuleX Enterprise" for the top tier — never a standalone "Enterprise" product, because Enterprise is a tier of ModuleX, not a separate product.
**ModulexAI, LLC** is the legal entity that operates the Service, a Delaware limited liability company. You will see "ModulexAI" as the legal name in metadata and in the copyright line. In legal and procurement documents, the company is ModulexAI, LLC; the product is ModuleX.
- **Product / brand:** `ModuleX` (one word, capital M and X).
- **Top tier:** `ModuleX Enterprise` — the Enterprise tier of ModuleX.
- **Legal entity:** `ModulexAI, LLC` (Delaware LLC), shown as the legal name `ModulexAI` in metadata and as `© ModulexAI` in the copyright line.
- **The Service:** the umbrella legal term for the ModuleX websites, applications, APIs, and related services.
- **Marketing site:** `https://modulex.dev`.
- **Documentation:** `https://docs.modulex.dev`.
ModuleX's brand voice is plain, specific, and confident. The product avoids buzzwords such as "streamline," "seamless," "empower," and "innovative." When you describe ModuleX Enterprise in your own materials, the clearest framing is the truest one: it is ModuleX, at enterprise scale.
## How to get ModuleX Enterprise
Free, Pro, and Max are self-serve — you choose them in the app. Enterprise is arranged with the ModuleX team, because the limits, deployment model, and support are tailored to your organization.
If you are new, build and run something first. The fastest path is the [quickstart](/get-started/quickstart) or [running your first workflow](/get-started/first-workflow). The platform you try is the platform Enterprise scales.
Decide which Enterprise capabilities matter for you — self-hosting, SSO and SAML, custom limits, dedicated support — using the differences above and [ModuleX for enterprise](/enterprise/overview).
Reach out through [contact sales](/enterprise/contact-sales) to size your limits, deployment, and support. Enterprise is the one tier that is arranged with a person rather than purchased self-serve.
## Where to go next
Why teams and enterprises choose ModuleX: collaboration, governance, and scale.
SSO, self-hosting, seats, and support for larger teams.
Free, Pro, Max, and Enterprise — allowances, limits, and how the tiers compare.
Single sign-on and self-hosted or managed deployment options for Enterprise.
Talk to the ModuleX team about Enterprise.
---
# Contact sales
URL: https://docs.modulex.dev/enterprise/contact-sales
Talk to the ModuleX team about an Enterprise plan — when to reach out, what to prepare, and how to start the conversation.
Enterprise is the only ModuleX plan that is **sales-led** — there is no self-serve checkout. You agree on scope, limits, and pricing with the ModuleX team, and your organization is configured to match. This page covers when to reach out, what to have ready, and how to start the conversation.
Enterprise is one of four ModuleX plans: **Free**, **Pro**, **Max**, and **Enterprise**. To see what Enterprise adds and why teams choose ModuleX, read [ModuleX for enterprise](/enterprise/overview). For the full side-by-side comparison of allowances and limits, see [Plans & pricing](/billing/plans).
## When to contact sales
Reach out when a fixed paid plan no longer fits how your organization works. The most common reasons:
Your team should sign in through your own identity provider instead of
managing individual ModuleX logins.
You need to run ModuleX in your own environment for data-residency or
infrastructure-control reasons.
You need custom rate limits or a credit allowance sized to your real usage,
rather than the Pro or Max caps.
You're adding many teammates across departments and want per-seat licensing
with no fixed cap.
You want a dedicated Slack channel with the ModuleX team rather than
community or email support.
You'd like guided setup to get your organization running quickly.
If you only need a couple of these and your usage fits within a fixed tier, compare [Plans & pricing](/billing/plans) first — you may not need Enterprise yet. If you're not sure, reach out anyway; the team can help you decide.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4330 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** A simple "is Enterprise right for you?" decision graphic.
**[IMAGE_DETAILS]:** A clean, friendly flow with a few yes/no branches — "Need SSO or self-hosting?", "Outgrown fixed limits?", "Rolling out to a large team?" — leading to either "Stay on Pro or Max" or "Talk to sales about Enterprise." Light and dark variants. Landscape, suitable for full content width. No screenshots of the app required.
## What to prepare
A short conversation goes faster when you arrive with a few details. None of these are required to reach out, but having them ready helps the team scope the right plan on the first call.
Roughly how many people will use ModuleX. The team typically works in these
brackets: 1–10, 11–50, 51–200, and 200+.
Which Enterprise features matter to you — for example single sign-on,
self-hosted deployment, custom limits, dedicated support, or onboarding. See
[ModuleX for enterprise](/enterprise/overview) for the full list.
A rough sense of how much you'll run — number of workflows, how often they
run, and whether you'll use ModuleX-managed models or [bring your own
keys](/billing/credits). This helps size your credit allowance and rate
limits.
Whether you need self-hosting, specific data-residency, or have a security
review process. For background, see the [Security overview](/security/overview)
and [Deployment & SSO](/enterprise/deployment-sso).
When you want to be up and running, and any procurement or review steps on
your side.
You don't have to figure out exact numbers before reaching out. The team will help you translate your needs into seats, limits, and a credit allowance during the conversation.
## How to reach the team
Start an Enterprise conversation in whichever way is easiest for you.
Write to **contact@modulex.dev** with your team size and what you're trying
to do. It's the fastest way to start.
Fill in the Enterprise contact form on the ModuleX website and the team will
follow up.
You can also reach Enterprise sales from inside the product: the Enterprise plan has no self-serve checkout, so choosing it directs you to contact the team rather than to a payment screen.
Have a question that isn't about Enterprise pricing — billing, an account issue, or a technical problem? Start at [Getting help](/help/getting-help) instead, which points you to the right channel.
## What happens next
Send your details by email or through the contact form.
You agree on seats, custom rate limits and credits, SSO, deployment, and the
support channel that fit your organization.
The ModuleX team sets up your Enterprise plan and helps you onboard your team.
## Common questions
No. Free, Pro, and Max are all self-serve — you can sign up and start without
talking to anyone. Sales is only for Enterprise, where scope, limits, and
pricing are agreed with the team. See [Plans & pricing](/billing/plans).
Yes. The Free plan includes trial credits and requires no credit card, so you
can build with the AI Composer and test real Assistant runs first. Then reach
out when you know you need Enterprise capabilities.
Enterprise pricing is custom — it's based on your seats, usage, and the
capabilities you need, rather than a fixed monthly price. The team will give
you a quote once your plan is scoped.
Enterprise replaces the fixed-tier caps with negotiated values — for example
your credit allowance and rate limits are configured per organization rather
than fixed at the Pro or Max tier. For how these work, see [Credits &
metering](/billing/credits) and [Usage gating & limits](/billing/usage-gating).
Anyone can start the conversation, but it helps if the person knows your team
size, expected usage, and any security or deployment requirements. In ModuleX,
organization roles are **owner** and **admin** — billing and plan changes
require one of these. See [Roles & permissions](/security/roles-permissions).
## Related pages
Why teams and enterprises choose ModuleX.
SSO, self-hosting, seats, custom limits, and support in detail.
Compare Free, Pro, Max, and Enterprise side by side.
---
# Deployment & SSO
URL: https://docs.modulex.dev/enterprise/deployment-sso
Single sign-on through Clerk and self-hosted vs. ModuleX-managed deployment for Enterprise: the entitlement flags that unlock them, just-in-time user provisioning, the production secrets a self-host requires, and the startup security gate.
This page covers the two Enterprise-only capabilities in this group: **single sign-on (SSO)** for your team, and **self-hosted deployment** of the ModuleX backend. Both are gated by per-plan entitlement flags that are set only on the **Enterprise** plan; everything below describes how each capability works against the verified backend behavior, what it requires, and which specifics are not pinned in source and are marked TBD.
Authentication mechanics referenced here are documented in full on [the authentication model page](/security/authentication); credential and secret encryption is documented on [the data security & encryption page](/security/data-encryption).
**Both capabilities are Enterprise entitlements.** In the plan configuration, `feature.sso` and `feature.self_host` are `true` only on the **Enterprise** plan and `false` on Free, Pro, and Max. They are surfaced as account feature flags; they are not toggles you set yourself. Talk to the team to enable them — see [contact sales](/enterprise/contact-sales).
## How SSO works in ModuleX
ModuleX has **one identity provider: Clerk.** The backend only ever *verifies* Clerk-issued JWTs — there are no first-party `/auth/login`, `/register`, `/logout`, or `/refresh` routes. The auth provider is read from `modulex.toml` as `[auth].provider`, which defaults to `"clerk"` and is the only configuration key that file consumes:
```toml modulex.toml
[auth]
provider = "clerk"
```
Because every human sign-in flows through Clerk, **enterprise SSO is delivered as a Clerk enterprise connection** (for example SAML or OIDC against your identity provider). When an SSO user signs in, Clerk mints a JWT, and the ModuleX backend verifies that JWT exactly as it would any other Clerk token. No separate SSO code path exists inside the ModuleX backend.
**SAML/OIDC connection details are configured in the Clerk dashboard, not in this repository — TBD.** The ModuleX source contains no SAML, OIDC, or SCIM implementation; the `feature.sso` flag is an entitlement signal, not enforcement code. The exact list of supported identity providers, the SAML/OIDC connection setup steps, the metadata/ACS URLs, and whether SCIM directory sync is offered are not pinned in source. Treat those specifics as **TBD** and confirm them with the ModuleX team before relying on them.
### What the backend verifies on every request
Whether a user arrives via SSO or ordinary Clerk sign-in, the token they carry is verified the same way. The verifier requires both `CLERK_JWKS_URL` and `CLERK_ISSUER` to be set; if either is missing, verification returns no claims and the request is rejected.
JWKS endpoint used to verify the JWT signature. JWKS responses are cached in-process with a 300-second TTL. Missing value disables JWT verification entirely.
Expected `iss` claim. The token is decoded with `issuer=CLERK_ISSUER`.
**Audience is not validated.** The backend decodes Clerk JWTs with `verify_aud: False`, so the token's audience (`aud`/`azp`) is not bound. The realtime server applies the same policy. Do not describe ModuleX as enforcing audience binding.
The claims read downstream are `sub` (the Clerk user id), `email`, `azp`, and `sid`. When the configured provider is `clerk`, the effective organization role is sourced from the JWT's `metadata.role`. See [the authentication model page](/security/authentication) for the full header-by-header breakdown, including the `Authorization: Bearer` forms and the Socket.io handshake.
### Just-in-time user provisioning
ModuleX provisions accounts **just in time (JIT)** on the first valid JWT for an unknown user. This is what makes SSO usable without manual seat setup: a user who signs in through your identity provider for the first time is created automatically.
A Clerk JWT for a user with no existing ModuleX record reaches the backend.
A `User` is created with the user-level role `USER`. (User-level roles are `USER` and `SUPER_ADMIN`; these are distinct from organization roles.)
A personal default organization is created, and the new user is added as its `owner`. The flow is idempotent and concurrent-safe, guarded by a row lock so a webhook-plus-JIT race cannot double-provision.
**There is no JIT path for API keys.** A `mx_live_*` API key cannot create a user — key creation is itself JWT-gated (`POST /api-keys` requires a signed-in user). So SSO/JIT provisioning applies to human sign-ins only; programmatic callers must already correspond to a provisioned user. See [the SDKs overview](/sdks/overview) for the programmatic path.
### Organization roles after SSO sign-in
Once provisioned, a user acts inside an organization under an organization role. The live roles are **`owner`** and **`admin`** only.
**The `member` role is retired.** It was retired on the backend and may still appear on old organization rows, in legacy invitation constraints, and in the realtime read-gate, but the REST edge rejects it everywhere (invite and role-update schemas enforce `admin` only). Document and plan around `owner`/`admin`. Note also that the agentic surfaces — Composer, Assistant, and schedules — require **owner/admin**, despite an older in-code comment suggesting any member can use the Assistant. Full detail is on [the roles & permissions page](/security/roles-permissions).
`owner` is assignable only at organization creation. Invitations and role updates are constrained to `admin` at the API edge. Organization scope itself is carried by the `X-Organization-ID` header on REST/SDK calls and by the Socket.io handshake `auth.organizationId` field on the realtime surface — see [org context & X-Organization-ID](/security/org-context).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4320 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** SSO sign-in and just-in-time provisioning sequence diagram.
**[IMAGE_DETAILS]:** Left-to-right flow: user → identity provider (IdP) → Clerk (mints JWT) → ModuleX backend (verifies JWT via JWKS) → first request triggers JIT provisioning (create User role `USER`, create default org, add owner membership). Show the `CLERK_JWKS_URL` / `CLERK_ISSUER` verification step and a side note that audience is not validated. Light theme, 16:9, no real names.
## Deployment options
ModuleX runs in two shapes. The default is **ModuleX-managed** (cloud); **self-hosted** is an Enterprise-only entitlement.
The default. ModuleX operates the backend, realtime server, database, and secret storage. Available on every plan. Authentication, secrets, and the production security gate are managed for you.
Enterprise only (`feature.self_host = true`). You operate the ModuleX backend in your own environment and supply the required configuration and secrets described below. Talk to the team via [contact sales](/enterprise/contact-sales).
**Self-hosting is gated by the `self_host` entitlement.** In the plan configuration, `feature.self_host` is `true` only on Enterprise. There is no public self-service installer documented in source. The packaging, container images, and orchestration topology for a customer self-host are **TBD** — confirm the supported deployment artifacts with the ModuleX team.
### Self-host requirements
A self-hosted backend sources its configuration through a single settings layer, resolving each secret **environment variable first, then Azure Key Vault, then default**. The following are the configuration values a production self-host depends on. Types and defaults are as defined in the backend configuration.
Canonical environment name; drives all production-only enforcement. Aliases are normalized: `prod` becomes `production`, `stage` becomes `staging`. Set to `production` for a real deployment. The values `production` and `staging` are the two that trigger the hard security gate below.
Symmetric key used to encrypt integration credentials. **Required in `production`/`staging`** (minimum length 32 = 256-bit). In development it defaults to an empty string and the app logs an insecure-key warning. Generate with `python3 -c "import secrets; print(secrets.token_urlsafe(32))"`.
If this key changes, all previously encrypted credential data becomes unrecoverable. Treat it as permanent for the lifetime of the data.
Pepper mixed into API-key hashing (`SHA-256(API_KEY_PEPPER + key)`). **Required in `production`/`staging`** (minimum length 32). Generate with `python3 -c "import secrets; print(secrets.token_hex(32))"`.
`API_KEY_PEPPER` is production-required but is **absent from the shipped `.env.example`**. A self-host that copies the sample file will not know to set it, and the app will fail the startup security gate. Set it explicitly.
PostgreSQL DSN. **Required in `production`/`staging`** (empty value is an error in those environments, a warning otherwise). Use the async driver form, for example `postgresql+asyncpg://user:pass@db:5432/modulex`.
Redis connection string. Used for caching, rate limiting, and realtime coordination.
JWKS endpoint for verifying Clerk JWTs. Required for any human sign-in (including SSO). Missing value disables JWT verification.
Expected JWT `iss` claim; must match the issuer your Clerk instance mints.
Gate for the platform `/admin/*` cross-organization monitoring routes. Comma-separated to allow zero-downtime rotation. An empty list makes the admin gate **fail closed** (no access). Generate with `openssl rand -hex 32`.
When set, secrets are sourced from Azure Key Vault after the environment variable lookup. Authentication uses the Container App system-assigned managed identity with the "Key Vault Secrets User" role. When unset (local/dev), only environment variables are read.
Server base URL used to build OAuth callback URLs.
Frontend origin.
CORS allowed hosts; split on commas and stripped.
Frontend base the backend redirects to after an OAuth token exchange.
Frontend landing path after OAuth; reads `status`, `integration`, `credential_id`, `error_code`, and `message` query parameters.
Per-key requests per minute.
Total per-user requests per minute.
Maximum number of API keys per user.
API key for the read-only diagnostics endpoint. When empty, the endpoint is disabled and returns `503`.
Selects a capacity preset (`small`, `medium`, `large`, `enterprise`, `azure_e8ds_v5`, `azure_e8ds_v5_peak`). An unknown name falls back to per-variable overrides such as `MAX_CONCURRENT_EXECUTIONS` (default `50`), `REQUEST_TIMEOUT` (default `30.0`), and `MAX_QUEUE_SIZE` (default `200`).
**Casing on the wire.** Environment variables are `UPPER_SNAKE_CASE`. When sourced from Azure Key Vault, secret names are `UPPER-KEBAB-CASE` (underscores become hyphens) — for example `ENCRYPTION_KEY` is stored as `ENCRYPTION-KEY` and `API_KEY_PEPPER` as `API-KEY-PEPPER`. The conversion is automatic.
**Key Vault rotation needs a restart.** The Key Vault secret resolver is cached for the process lifetime, so rotating a secret in the vault is not picked up until the process restarts. Environment-sourced values are likewise read once at startup.
### The production startup security gate
On startup, the backend validates the security-critical secrets. The behavior depends on `ENVIRONMENT`:
| Condition | `production` / `staging` | `development` |
| --- | --- | --- |
| `ENCRYPTION_KEY` missing | Startup fails | Warning, continues with empty key |
| `ENCRYPTION_KEY` shorter than 32 chars | Startup fails | Warning, continues |
| `API_KEY_PEPPER` missing | Startup fails | Warning, continues with empty pepper |
| `API_KEY_PEPPER` shorter than 32 chars | Startup fails | Warning, continues |
| `DATABASE_URL` empty | Startup fails | Warning, continues |
In `production`/`staging`, any validation error prints `❌ SECURITY VALIDATION FAILED` and the process exits with code `1`. In development the process prints an insecure-settings warning and continues. On success it logs that security settings were validated.
### Minimal production environment
```bash .env (self-host)
# Identity / encryption (REQUIRED in production, >=32 chars each)
ENCRYPTION_KEY="$(python3 -c 'import secrets; print(secrets.token_urlsafe(32))')"
API_KEY_PEPPER="$(python3 -c 'import secrets; print(secrets.token_hex(32))')" # NOT in .env.example
ENVIRONMENT=production # or "prod" -> normalized to production
DATABASE_URL=postgresql+asyncpg://user:pass@db:5432/modulex # required in prod
REDIS_URL=redis://cache:6379
# Clerk auth (required for human sign-in, including SSO)
CLERK_JWKS_URL=https://clerk.example.com/.well-known/jwks.json
CLERK_ISSUER=https://clerk.example.com
# Platform admin gate (fails CLOSED if empty); rotate via comma-separated list
ADMIN_DASHBOARD_API_KEYS="$(openssl rand -hex 32)"
```
```bash .env (Key Vault variant)
# Same as above, but source the security secrets from Azure Key Vault.
# Store them in the vault as ENCRYPTION-KEY and API-KEY-PEPPER (kebab-case).
ENVIRONMENT=production
DATABASE_URL=postgresql+asyncpg://user:pass@db:5432/modulex
REDIS_URL=redis://cache:6379
CLERK_JWKS_URL=https://clerk.example.com/.well-known/jwks.json
CLERK_ISSUER=https://clerk.example.com
ADMIN_DASHBOARD_API_KEYS="$(openssl rand -hex 32)"
# Enables Key Vault sourcing; ENCRYPTION_KEY / API_KEY_PEPPER resolved from the vault.
AZURE_KEY_VAULT_URL=https://my-vault.vault.azure.net/
```
**Operational details that are not pinned in source — TBD.** The process/worker runtime (host, port, worker count), container images and orchestration topology, backup/restore procedures, and any Celery or telemetry configuration are not documented in the configuration source. The backend exposes no `PORT`, `WORKERS`, `HOST`, or `SENTRY_*` environment variables, which suggests those are supplied by the process manager or compose stack rather than by application config. Confirm the supported runtime with the ModuleX team.
## Provisioning and seats
User provisioning is JIT, as described above — new SSO users are created on first sign-in with an owner default organization. **Directory-driven provisioning and de-provisioning (SCIM) is not implemented in source and is TBD.**
Seat limits come from plan entitlements, not from a deployment setting:
| Plan | Seat quota | Self-host | SSO |
| --- | --- | --- | --- |
| Free | 5 | No | No |
| Pro | Per-seat licensed | No | No |
| Max | Per-seat licensed | No | No |
| Enterprise | Custom / per-seat licensed | Yes | Yes |
A `seats` quota of `null` means the plan is per-seat licensed (billed, not capped at a fixed number). Enterprise sets `feature.self_host` and `feature.sso` to `true`; all other plans set both to `false`. For the full plan comparison and the credit and rate-limit allowances, see [plans & pricing](/billing/plans).
**Enterprise annual pricing is unresolved — present both figures.** The marketing site advertises Pro annual at `$240/yr` and Max annual at `$960/yr` (a 20% discount), while the backend Stripe configuration prices the annual SKUs at `$300/yr` and `$1,200/yr` (full monthly × 12, no discount). The authoritative annual price is an open question; do not pick a winner here. Always confirm the actual charge at checkout, and see [plans & pricing](/billing/plans) for the canonical figures.
## Requirements at a glance
- An Enterprise plan with `feature.sso = true`.
- A Clerk enterprise connection configured against your identity provider (SAML/OIDC). Connection setup lives in the Clerk dashboard and is **TBD** in this documentation.
- `CLERK_JWKS_URL` and `CLERK_ISSUER` configured on the backend (managed for you on cloud).
- Users are provisioned JIT on first sign-in as organization `owner` of a default org; live roles are `owner`/`admin`.
- An Enterprise plan with `feature.self_host = true`.
- `ENVIRONMENT=production` (or `staging`).
- `ENCRYPTION_KEY` and `API_KEY_PEPPER`, each at least 32 characters — both production-required, and `API_KEY_PEPPER` is missing from the sample env file.
- A PostgreSQL `DATABASE_URL` (async driver) and a `REDIS_URL`.
- `CLERK_JWKS_URL` and `CLERK_ISSUER` for sign-in.
- `ADMIN_DASHBOARD_API_KEYS` if you use the platform admin dashboard (the gate fails closed when empty).
- Optionally, `AZURE_KEY_VAULT_URL` to source secrets from Azure Key Vault.
- The startup security gate exits the process with code `1` if any required secret is missing or too short in `production`/`staging`.
- Container images, orchestration, and runtime topology are **TBD** — confirm with the ModuleX team.
## Related
Clerk JWT verification, `mx_live_*` API keys, and the header forms every caller uses.
How credentials and secrets are encrypted, and the production security checks.
The live `owner`/`admin` role model and what each can do.
Enable SSO and self-hosting on an Enterprise plan.
---
# ModuleX for enterprise
URL: https://docs.modulex.dev/enterprise/overview
ModuleX scales from one person to a whole organization: realtime team collaboration, owner/admin governance, org-scoped credits and billing, and BYOK or managed usage. Built on the same platform your team already knows.
You can start ModuleX as one person with one idea. As your team grows, the same platform grows with you: the workflows you built solo become shared, the credentials your team connects become governed, and your usage becomes something you can see, scope, and control across the whole organization. This page is the value picture for teams and enterprises. For the security architecture behind it, see [security overview](/security/overview).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4300 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** A single value-overview graphic showing the three enterprise pillars — Collaboration, Governance, Scale — as one connected story.
**[IMAGE_DETAILS]:** Authored illustration (not an app capture). Three labelled panels left to right: "Collaborate" (multiple cursors on one workflow canvas), "Govern" (an organization with owner/admin roles and a credential vault), "Scale" (a usage/credits meter and higher rate limits). Keep it calm and diagrammatic, sentence-case labels, light theme, 16:9. No fabricated logos or metrics.
## From one person to a whole organization
ModuleX is an AI workflow orchestration platform. The way you build and run work does not change as you scale — what changes is who you do it with, and how much control you have over it.
Your team co-edits the same [workflow](/concepts/workflows-and-runs) on a live canvas, runs from chat, API, or SDK, and shares one [knowledge base](/concepts/knowledge-rag) — instead of passing files and prompts around.
Every workflow, run, credential, and knowledge base belongs to an [organization](/concepts/organizations-roles). Owner and admin roles decide who can build, connect tools, and run agentic surfaces.
Higher plans raise your run rates, API limits, and credit allowance. On the Enterprise plan, rate limits and credits are custom, and deployment can move to your own infrastructure.
The rest of this page walks through those three pillars — collaboration, governance, and scale — and points to the deeper reference for each. When you are ready to talk to the team, head to [contact sales](/enterprise/contact-sales).
## Collaboration: your team works on one canvas
Most automation tools assume one builder. ModuleX assumes a team. The [workflow builder](/workflow-builder/overview) is a realtime, multi-user canvas, so several people can shape the same workflow at the same time and see each other's changes as they happen.
Multiple people edit one canvas together. You see who else is present, where their cursor is, and which nodes are being worked on. See [presence, locks and versioning](/realtime/presence-locks).
Workflows, knowledge bases, credentials, and chats live in the organization, not on one person's laptop. Anyone with access works from the same source of truth.
The [AI Composer](/workflow-builder/composer) turns a plain-English description into an editable workflow graph your team can refine — a fast shared starting point, not a black box.
Keep conversations personal, or make them organization-visible so teammates can pick up, review, and continue the work.
Live team collaboration is available on the Pro, Max, and Enterprise plans; the Free plan is a solo workspace. See [plans and pricing](/billing/plans) for what each plan includes.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4301 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** Two teammates co-editing the same workflow canvas in realtime.
**[APP_VIDEO_DETAILS]:** Screen-record the ModuleX app builder with two cursors visible. Show one person adding a node while the other repositions an edge, with presence avatars and a node lock appearing. 20-30s, 16:9, light theme, no narration, no real customer data. Highlight the two cursors and the presence indicators.
For how edits stay in sync across collaborators and external changes, see [realtime co-editing and external sync](/workflow-builder/realtime-coediting).
## Governance: clear ownership over access and data
As more people build, you need to know who can do what. In ModuleX, the [organization](/concepts/organizations-roles) is the unit of tenancy and billing: every workflow, run, credential, knowledge base, and wallet is scoped to one organization, and access is decided by org roles.
### Roles that map to responsibility
ModuleX uses two active organization roles. The agentic surfaces — the [AI Composer](/concepts/ai-composer), the [Assistant](/assistant/overview), knowledge management, and schedules — require the **owner** or **admin** role.
Full control of the organization, including billing and membership. The owner can do everything an admin can, plus manage the plan.
Can build and edit workflows, connect tools, manage knowledge, and run the agentic surfaces. Admins handle day-to-day building and operations.
The older `member` role has been retired and is not a current first-class role. Where the app still references it, treat it as a known gap — see [roles and permissions](/security/roles-permissions) and [known limitations](/reference/known-limitations). Plan your access model around **owner** and **admin** only.
### Credentials stay in the organization
The keys your team connects — the credentials behind every [integration](/integrations/overview) — are stored against the organization, encrypted at rest, and resolved at run time rather than handed back out. Your team connects a service once; everyone who is authorized can use it without anyone copying secrets around.
Connect a tool once for the organization. Credentials are stored encrypted and never re-exposed after they are saved.
Programmatic access selects an organization with the `X-Organization-ID` header, so each call is scoped to exactly one tenant's data.
For how secrets are encrypted and how access is enforced, see [data security and encryption](/security/data-encryption) and the full [security overview](/security/overview).
### Visibility over usage
The public pricing surface lists usage and analytics, and audit-log visibility, across the plans, with advanced analytics on Max and Enterprise. The exact scope of audit logging is set on the platform rather than pinned in this research base, so treat the detailed audit-log coverage as **TBD** until it is confirmed on [trust and compliance](/security/trust). What is firm: usage is metered per organization in [credits](/concepts/credits-billing), and that record is the basis for the analytics each plan exposes.
## Scale: grow run rates, usage, and deployment
The same workflows run whether you are one person or a thousand — but how much you can run, and where it runs, depends on your plan. The limits and credit allowances below come from the canonical backend plan configuration; see [plans and pricing](/billing/plans) and [credits and metering](/billing/credits) for the full picture.
Free
Pro
Max
Enterprise
**Credits**
300 (one-time trial)
5,000 / mo
20,000 / mo
Custom
**API rate limit**
10 / min
100 / min
500 / min
Custom
**Workflow execution**
10 runs / min
150 runs / min
500 runs / min
Custom
**Live team collaboration**
—
Yes
Yes
Yes
**Self-hosted deployment**
—
—
—
Yes
**SSO / SAML**
—
—
—
Yes
**Onboarding**
—
—
—
Hands-on
**Support**
Community
Discord
Email + Discord
Dedicated
The asynchronous workflow-execution rate that higher plans advertise is configured but not yet enforced, so today's effective limit is the per-minute run rate shown above. Credit and rate-limit numbers are pinned to the backend plan configuration; the public pricing page is the place to confirm current figures at checkout. See [plans and pricing](/billing/plans).
### Pay your way: BYOK or managed credits
Cost control is part of scaling. ModuleX gives you two billing models, and you can mix them.
Connect your own model and tool provider accounts. The provider bills you directly with no ModuleX markup, so your AI spend stays on your existing accounts.
Use ModuleX-provisioned providers and pay in [credits](/concepts/credits-billing) — no setup, with usage metered per organization. Managed usage is what your plan's allowance covers.
BYOK is presented as available across all plans. Because BYOK usage is billed by the provider, it is not metered in ModuleX credits — it shows up in analytics only. See [credits and metering](/billing/credits).
### Deploy where you need it
On the Enterprise plan, ModuleX can run on your own infrastructure, with single sign-on for your identity provider.
Sign in through your identity provider. SSO and SAML are Enterprise-plan capabilities. See [deployment and SSO](/enterprise/deployment-sso).
Run ModuleX in your own environment for full control over where your data and runs live, with custom rate limits and credits.
## What the Enterprise plan adds
The Enterprise plan is for organizations operating at scale. Its capabilities, as listed on the public Enterprise offering, are:
Sign in through your identity provider.
Run ModuleX in your own environment.
Limits and allowances sized to your workload instead of fixed plan tiers.
Deeper usage visibility for the organization. Detailed audit-log scope is TBD pending [trust and compliance](/security/trust).
A dedicated support channel for your team.
Guided onboarding to get your organization running.
Enterprise pricing is custom. The capabilities above mirror the public Enterprise offering; the Free, Pro, and Max plans are self-serve. For a side-by-side of every plan, see [plans and pricing](/billing/plans), and for the SSO and self-hosting reference, see [the Enterprise security page](/security/enterprise).
## Trust and compliance
Security is covered in depth in its own [security overview](/security/overview): the [authentication model](/security/authentication), [organization context](/security/org-context), [roles and permissions](/security/roles-permissions), and [data security and encryption](/security/data-encryption).
This research base does not pin any formal compliance certification (for example SOC 2, ISO 27001, or specific regulatory programs), and ModuleX's published terms state the service is not designed for use under regulated regimes such as HIPAA, GLBA, or PCI-DSS. Do not assume a certification that is not confirmed. The authoritative, current statement of compliance posture and sub-processors lives on [trust and compliance](/security/trust), [compliance](/security/compliance), and [sub-processors](/security/sub-processors) — treat any certification claim as **TBD** until it appears there.
## Built on org-scoped access
Everything above rests on one idea: each request acts inside exactly one organization. When your team works programmatically, every call carries the API key plus the organization it acts on — the same governance boundary you see in the app. Authentication uses `Authorization: Bearer mx_live_…` together with the `X-Organization-ID` header; see [authentication](/api-reference/authentication).
The example below lists the workflows in one organization. Swap the organization id to act inside a different tenant — the access boundary travels with the header.
```bash cURL
curl https://api.modulex.dev/workflows \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: org_your_organization_id"
```
```python Python
from modulex import Modulex
client = Modulex(api_key="mx_live_your_api_key")
workflows = client.workflows.list(
organization_id="org_your_organization_id",
)
for workflow in workflows:
print(workflow.id, workflow.name)
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({ apiKey: "mx_live_your_api_key" });
const workflows = await client.workflows.list({
organizationId: "org_your_organization_id",
});
for (const workflow of workflows) {
console.log(workflow.id, workflow.name);
}
```
For the full developer surface, see the [API overview](/api-reference/overview) and the [SDKs overview](/sdks/overview).
## Common questions
An organization is the tenant and billing unit. Workflows, runs, credentials, knowledge bases, and the credit wallet all belong to an organization, and access is decided by org roles. You can belong to more than one organization and switch between them. See [organizations, roles and membership](/concepts/organizations-roles).
The agentic surfaces — the AI Composer, the Assistant, knowledge management, and schedules — require the **owner** or **admin** role. The `member` role has been retired. See [roles and permissions](/security/roles-permissions).
Yes. With BYOK you connect your own provider accounts and the provider bills you directly with no ModuleX markup. You can also use ModuleX-managed credits, and mix the two. See [credits and metering](/billing/credits).
Self-hosted deployment is an Enterprise-plan capability, alongside SSO and SAML and custom limits. See [deployment and SSO](/enterprise/deployment-sso) and [the Enterprise security page](/security/enterprise).
Compliance posture and sub-processors are documented on [trust and compliance](/security/trust), [compliance](/security/compliance), and [sub-processors](/security/sub-processors). Any specific certification should be confirmed there rather than assumed; this research base does not pin one.
Enterprise pricing is custom. Tell us about your team and we will follow up. See [contact sales](/enterprise/contact-sales).
## Talk to the team
If your organization needs custom limits, self-hosting, SSO, or hands-on onboarding, the Enterprise plan is built for you.
Tell us about your team — size, the tools you use, and what you want to automate — and we will help you find the right plan. Enterprise pricing is custom.
Compare Free, Pro, Max, and Enterprise side by side, including allowances and limits.
SSO, self-hosting, seats, and support, for larger teams.
How ModuleX secures your data, credentials, and access.
Single sign-on and self-hosted deployment options for enterprise.
---
# Architecture overview
URL: https://docs.modulex.dev/get-started/architecture
How ModuleX fits together: one FastAPI backend, a Next.js app, a Socket.io realtime server, two SDKs, and an installable tool catalog, bound by one Postgres, one Redis, and Clerk.
{/* AUDIENCE: technical. Feeds: X01 (architecture), B01 (REST overview), B19 (inter-repo contracts). */}
ModuleX is a system of seven repositories built around a single backend. One FastAPI service owns the database, the credit ledger, the tool runtime, and every REST and SSE surface. A Next.js app is the only first-party human surface; it talks to the backend over REST and SSE and to a separate Socket.io server for realtime canvas collaboration. Two SDKs wrap the same REST surface, and the integration tool catalog ships as an installable Python package the backend loads at startup.
This page maps the components, the wires between them, the boot order, the auth context that threads through every hop, and the parts of the system you should not build against because they are inert today.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1060 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** ModuleX component-and-data-flow diagram covering all seven repositories.
**[IMAGE_DETAILS]:** Recreate the text diagram in section "Component and data-flow map" as a clean architecture illustration. Show the browser, `modulex-ui` (Next.js, :3000, BFF proxy that adds `Authorization: Bearer` + `X-Organization-ID`), `modulex-ws` (Socket.io, :3001), and `modulex` (FastAPI, :8000) as a central column; below it the three shared backplanes (Postgres incl. the Procrastinate schema, Redis, Stripe) and the installed `modulex-integrations` package reached over the `modulex.tools` entry-point group; off to the side Clerk (external IdP) at the top and the two SDKs (`modulex-js`, `modulex-python`) calling the backend over REST. Label the realtime split: SSE for run events, Socket.io for canvas collaboration. 16:9, light and dark variants, no decorative gradients.
## The seven repositories
Seven repositories make up ModuleX, but only five of them run as processes — two are libraries and one is a static marketing site.
| Repository | Stack | Role | Listens on |
| --- | --- | --- | --- |
| `modulex` | Python 3.12, FastAPI (Pydantic v2) | The backend: all REST and SSE, auth, billing, the tool runtime, the workflow, Composer, and Assistant engines, and the background worker | `:8000` (dev canonical) |
| `modulex-ui` | Next.js 15 / React 19 (App Router) | The first-party web app and a thin backend-for-frontend (BFF) proxy layer | `:3000` |
| `modulex-ws` | Node 20 / TypeScript, Socket.io | The realtime multi-user canvas collaboration server | `:3001` |
| `modulex-integrations` | Python 3.12 package | The installable tool catalog (175 integrations) loaded by the backend | — (library) |
| `modulex-js` | TypeScript SDK | The JavaScript/TypeScript client wrapping the REST surface | — (library) |
| `modulex-python` | Python SDK | The async Python client wrapping the REST surface | — (library) |
| `modulex-www` | Static marketing site | The public marketing and pricing site | — (static) |
The backend serves on `http://localhost:8000` in development; that is the canonical base URL for every example in these docs. (A `python -m app.main` shortcut binds `8001` to avoid local conflicts, but the standard `uvicorn` command and all tooling use `8000`.) The SDKs default to the production REST host `https://api.modulex.dev`.
The integration count is **175 live integrations** — the figure to use anywhere a tool count appears. A vendored `dist/manifests.json` snapshot in `modulex-integrations` lags at 136 entries; do not quote it. See the [integration catalog](/integrations/catalog) for the authoritative list.
## The three shared backplanes
Every component above is wired together by exactly three external services.
The authoritative datastore. The backend is the only authoritative writer; `modulex-ws` does its own reads and writes against the same database. The Procrastinate job queue lives in a dedicated `procrastinate` schema in the same Postgres.
Used by the backend for run-event pub/sub, history replay, rate-limit counters, caches, and credit reservation; used by `modulex-ws` as the Socket.io adapter and for presence and lock keys.
The external identity provider. It issues the user JWTs that the backend, the app, and the realtime server all verify against Clerk's JWKS.
The Postgres and Redis instances are shared, but the ownership boundaries are strict:
- The backend **never** reads or writes the `presence:*` or `lock:workflow:*` Redis keys. Those belong exclusively to `modulex-ws`.
- The only Redis surface the two backends are designed to share is pub/sub channels — and even that bridge is inert today (see [Components you should not build against](#components-you-should-not-build-against)).
## Component and data-flow map
```text
┌──────────────────────────┐
│ Clerk (external IdP) │
│ JWT issue + JWKS │
└───┬──────────────┬────────┘
sign-in / JWT │ │ JWKS verify
│ │
┌─────────────────────────▼─┐ ┌──▼──────────────────────┐
browser │ modulex-ui (Next.js :3000) │ │ modulex-ws (Socket.io │
─────────►│ • App Router pages │ │ :3001) │
│ • app/api/* BFF proxies │ │ • canvas collaboration │
│ (add Bearer + X-Org-ID) │ │ • presence / locks │
└───┬───────────────┬────────┘ └────┬───────────┬────────┘
REST + SSE │ │ Socket.io │ Socket.io │ shared
(proxied) │ └───────────────────────┘ │ Postgres + Redis
│ │ (own reads)
▼ │
┌───────────────────────────────────────────────────────────────┴──────────┐
│ modulex (FastAPI :8000) │
│ • 21 routers (REST) • SSE: workflow:run:{run_id}:events (Redis) │
│ • auth/org dependencies • workflow / Composer / Assistant engines │
│ • tool runtime ───────────────────────► loads @tool from modulex-integr. │
│ • billing / credit ledger • Procrastinate worker (separate process) │
└───┬───────────────┬───────────────────┬──────────────────────┬────────────┘
│ Postgres │ Redis │ entry-point group │ Stripe
▼ ▼ ▼ "modulex.tools" ▼ (external)
┌────────┐ ┌──────────┐ ┌──────────────────────┐
│Postgres│ │ Redis │ │ modulex-integrations │
│(+ proc-│ │(pub/sub, │ │ (installed package, │
│ rastin-│ │ cache, │ │ 175 tools) │
│ ate) │ │ rate-lim)│ └──────────────────────┘
└────────┘ └──────────┘
SDKs: modulex-js / modulex-python ──REST──► modulex (:8000)
Docs: modulex-www (static marketing site, no runtime wire)
```
## The five deployables
There are five things that actually run. The other repositories are libraries (`modulex-integrations`, `modulex-js`, `modulex-python`) or a static site (`modulex-www`).
| Unit | From repository | Process |
| --- | --- | --- |
| API server | `modulex` | `uvicorn app.main:app` (`:8000`) |
| Background worker | `modulex` | `python -m app.workers.run_worker --queue default --queue ingest` |
| App server | `modulex-ui` | Next.js (`:3000`) |
| Realtime server | `modulex-ws` | `node dist/index.js` (`:3001`) |
| (libraries / static) | `modulex-integrations`, `modulex-js`, `modulex-python`, `modulex-www` | not a process |
The background worker is a separate process from the API server and does **not** run the API's startup lifespan. Tasks that need Redis (such as organization-usage refresh and the credit-reservation sweeper) connect to Redis themselves rather than relying on a shared client wired during API startup.
### Boot order
The two long-lived servers each have a deterministic startup sequence.
The root log level comes from `LOG_LEVEL` (default `INFO`).
In `production` or `staging`, a failed security check aborts startup. In development it logs a warning and continues.
Applies migrations and syncs the integration catalog from the installed `modulex-integrations` package into the database.
Falls back to an in-memory implementation if Redis is unreachable.
Wires the run-event delivery machinery (multi-instance aware).
The LangGraph state checkpointer is always the Postgres saver.
All 21 REST routers mount at their resource prefixes. There is no `/v1` segment.
Opens three ioredis clients (default, subscriber, publisher).
Runs `SELECT 1` against the shared database.
Exposes `/health` and `/admin/*`.
The adapter lets multiple realtime instances broadcast to one another.
The handshake gate verifies the Clerk JWT and resolves org membership before any event handler runs.
Binds node, edge, lock, cursor, presence, and patch handlers, then listens on `:3001`.
## The REST surface
The backend exposes 21 routers, mounted directly at their resource prefixes (`/workflows`, `/composer`, `/assistant`, `/knowledge-bases`, `/credentials`, and so on). There is **no API version segment** — no `/v1` or `/api/v1`. Trailing-slash redirects are disabled, so a path is matched exactly as written.
Every response body is **snake_case** JSON (Pydantic v2 default); request headers are PascalCase-hyphen (`X-Organization-ID`, `X-API-KEY`). The full request lifecycle, content types, and base URLs are covered in the [API overview](/api-reference/overview); the environments and versioning policy live in [Base URLs, environments & versioning](/get-started/environments).
### Standard error envelopes
The backend emits **three** error-envelope shapes, and you must branch on all of them. Each is owned by a different surface:
| Shape | Example | Where it comes from |
| --- | --- | --- |
| `{"detail": ""}` | `{"detail": "X-Organization-ID header is required"}` | The common FastAPI `HTTPException` on CRUD and org-settings routes |
| `{"detail": {…}}` | `{"detail": {"code": "rate_limited", "layer": "rate", "key": "api", "current": 300, "limit": 300}}` | The org-level rate-limit deny |
| Flat `{"code", "layer", "key", "current", "limit", "reason"}` | `{"code": "credit_plan_exhausted", "layer": "credit", "key": "run", "current": 5000, "limit": 5000, "reason": "plan_credits_exhausted"}` | The billing/credit admission gate (`DenialEnvelope`) on run surfaces |
The complete shape catalog, status mapping, and which surface emits each lives in [Errors & status codes](/api-reference/errors).
The billing/credit admission gate is **live** on the run, [Composer](/concepts/ai-composer), [Assistant](/assistant/overview), and managed-knowledge surfaces. Calls to those surfaces can return a flat `DenialEnvelope` as **402** (credit or wallet), **403** (quota), or **429** (rate) — alongside the existing rate-limit-header 429. Plain CRUD and org-settings routes do **not** return this envelope; they return the `{"detail": …}` `HTTPException` shape. See [Usage gating & limits](/billing/usage-gating).
## Auth and org context across every hop
The same two pieces of context — a **Clerk JWT** (or an `mx_live_` API key) and an **organization id** — thread through every wire, but the transport differs per hop.
| Hop | Identity token | Org context |
| --- | --- | --- |
| Browser → app | Clerk session | `selected_organization_id` cookie |
| App BFF → backend (REST) | `Authorization: Bearer ` | `X-Organization-ID` header |
| Backend dependency | Bearer JWT **or** `mx_live_*` API key | `X-Organization-ID` header (or `?organization_id` query) |
| Browser → realtime server | `auth.token` (Clerk JWT) in the Socket.io handshake | `auth.organizationId` in the handshake |
| SDK → backend | `mx_live_*` API key (or Clerk JWT) | `X-Organization-ID` header |
The auth header is `Authorization: Bearer mx_live_…`, **not** `X-Authorization`. Both SDKs send `Authorization: Bearer` plus `X-Organization-ID`; the backend also accepts the key in an `X-API-KEY` header as an alternative. There is no `X-Authorization` header anywhere in the system. See [Authentication](/api-reference/authentication).
The org context header is `X-Organization-ID` (exact casing) on every REST and SSE hop. The realtime server resolves org membership independently, through its own Redis-cached SQL lookup. The full model — Clerk JWT versus API key, roles, and the org header — is in [Auth model: JWT vs API key](/security/authentication) and [Org context & X-Organization-ID](/security/org-context).
Live org roles are **`owner`** and **`admin`** only — the `member` role is retired. Composer, Assistant, and managed-knowledge actions require owner or admin. See [Roles & permissions](/security/roles-permissions).
## Two realtime planes
ModuleX has two realtime systems that do not share a transport.
Owned by the backend, delivered over **SSE** on top of Redis pub/sub. Carries workflow, Composer, and Assistant run progress: `metadata`, `node_update`, `tool_call`, `interrupt`, `done`, and more. Run endpoints emit flat `data: {"type": …}` frames; the discriminator is the `type` key inside the JSON, with no `event:` line.
Owned by `modulex-ws`, delivered over **Socket.io**. Carries presence, cursors, node locks, node and edge edits, and external sync. The handshake takes the Clerk JWT and the org id; events are `node:add`, `patch`, `lock`, and the like.
On reconnect, the SSE path is replay-safe: the listener first re-yields the run's Redis history list (one-hour TTL) in order, then tails live. Run-event delivery is Redis-pub/sub-native, so any backend replica subscribed to `workflow:run:{run_id}:events` receives events published by any other replica. The realtime server scales horizontally through the Socket.io Redis adapter. The end-to-end model is in [Realtime overview & event taxonomy](/realtime/overview) and the [realtime & collaboration model](/concepts/realtime-model).
Not all SSE in the system uses the same frame convention. Run and agent streams use flat typed-JSON `data.type` frames; the sidebar chat-list stream (`GET /chats/stream`) uses **named** SSE events (`event: chat_list_updated`). A consumer that crosses both must expect both conventions.
## The tool runtime seam
The most architecturally significant internal seam is how the backend turns a catalog name such as `github.create_issue` into an executed, billed action against the installed [integrations](/integrations/overview) package.
At startup, the backend queries Python entry points in the `modulex.tools` group from the installed `modulex-integrations` package and caches the result for the process lifetime. Restart the worker to pick up a freshly installed package version.
The startup sequence syncs the catalog into the database. The runtime then reads auth schemas from the **database** catalog, not from live package manifests — so a new manifest field is inert until the catalog is re-synced against the bumped package.
The backend imports each tool's `@tool`-decorated function and wraps it so that credential fields are stripped before the model ever sees them.
The executor resolves and decrypts the credential (refreshing OAuth2 tokens that are close to expiry), injects auth into the call, and invokes the tool. Tools run only inside workflow runs and Composer or Assistant turns — there is no REST endpoint for direct tool execution.
Managed (`modulexai`) usage is metered in [credits](/billing/credits); bring-your-own-key (BYOK) credentials are tracked but not credit-limited.
Most integrations come from the `modulex-integrations` package, but not all: legacy JSON-defined integrations such as `mcp_server` (which loads tools dynamically from a [custom MCP server](/integrations/building/custom-mcp) credential) are also loaded, and the package wins on a name collision. The full tool contract is in [Build an integration](/integrations/building/overview).
## SDK client configuration
Both SDKs wrap the same REST surface and send the same headers. The constructor shapes differ in one structural way: the Python client reads environment-variable fallbacks; the JavaScript client does not.
An `mx_live_…` API key. In Python this falls back to the `MODULEX_API_KEY` environment variable; in JavaScript it must be passed to the constructor or the client throws.
The organization id sent as `X-Organization-ID`. In Python it falls back to `MODULEX_ORGANIZATION_ID`; in JavaScript it is constructor-only.
The REST host. In Python it falls back to `MODULEX_BASE_URL`; in JavaScript it is constructor-only.
Per-request timeout. No environment fallback in either SDK.
Retry budget for retryable requests. No environment fallback in either SDK.
Configure a client and trigger one workflow run. The run accepts either `workflowId` (a deployed workflow) or an inline `workflow` definition, plus `input`, `config`, and `stream`.
```bash cURL
curl https://api.modulex.dev/workflows/run \
-H "Authorization: Bearer mx_live_2f8c9d1a4b6e7f0c3d5a8b2e" \
-H "X-Organization-ID: 7c1e9a4b-2d6f-4a83-9b15-0e2c8f6a1d34" \
-H "Content-Type: application/json" \
-d '{
"workflow_id": "wf_3a9c1e7b-5d24-4f81-bc06-2e8a9d4f1b73",
"input": { "topic": "Q3 release notes" },
"stream": true
}'
```
```python Python
import asyncio
from modulex import Modulex
async def main():
# api_key, organization_id, and base_url fall back to
# MODULEX_API_KEY / MODULEX_ORGANIZATION_ID / MODULEX_BASE_URL.
client = Modulex(
api_key="mx_live_2f8c9d1a4b6e7f0c3d5a8b2e",
organization_id="7c1e9a4b-2d6f-4a83-9b15-0e2c8f6a1d34",
)
async with client:
run = await client.executions.run(
workflow_id="wf_3a9c1e7b-5d24-4f81-bc06-2e8a9d4f1b73",
input={"topic": "Q3 release notes"},
stream=True,
)
print(run)
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from "modulex-js";
// apiKey and organizationId are constructor-only (no env fallback in JS).
const client = new Modulex({
apiKey: "mx_live_2f8c9d1a4b6e7f0c3d5a8b2e",
organizationId: "7c1e9a4b-2d6f-4a83-9b15-0e2c8f6a1d34",
});
const run = await client.executions.run({
workflowId: "wf_3a9c1e7b-5d24-4f81-bc06-2e8a9d4f1b73",
input: { topic: "Q3 release notes" },
stream: true,
});
console.log(run);
```
One wire-casing detail to keep in mind: the JavaScript SDK takes camelCase parameters and converts them to snake_case before sending, but it does **not** convert responses back — response fields stay snake_case (`run_id`, `created_at`). The Python SDK is snake_case in both directions. The full route-to-method mapping, naming differences, and parity gaps are in the [SDK ⇄ API parity matrix](/sdks/parity).
## Components you should not build against
A few wires exist in the codebase but are inert or unbuilt today. Build against the live path, not these.
The realtime server subscribes to literal Redis channels `workflow:updated` and `workflow:deleted`, but the backend publishes workflow-change events on per-workflow channels (`workflow:{id}:changes`). No backend publisher targets the flat channels, so those subscriptions never fire. Live external canvas sync flows over the **Socket.io `workflow:external-sync`** event, not the Redis bridge. See [Socket.io collaboration events](/realtime/socket-events) and [Realtime co-editing & external sync](/workflow-builder/realtime-coediting).
Several app calls have no target on the path they use and are documented as known limitations, not working flows: OAuth2 refresh from the app (the backend route exists but the app's proxy route is missing — reconnect the integration instead), the chat `sendMessage` call (no backend route), the templates surface (no router shipped), and the plural `nodes:delete` realtime emit (only the singular `node:delete` handler is registered). See [Known limitations](/reference/known-limitations).
The `subscriptions` resource exists only in the Python SDK; the JavaScript SDK has no equivalent. See [Subscriptions & Stripe](/billing/subscription-lifecycle) and the [parity matrix](/sdks/parity).
## How repositories stay in contract
The repositories deploy independently, so ModuleX coordinates breaking changes through a file-based "brief" protocol: the backend holds inbound brief directories (one per sibling repository), each a markdown file with an acknowledgment block. Two conventions hold across them:
- Breaking changes merge in the order **backend → realtime server → app**, with each side holding its branch until the upstream field lands.
- Any new integration manifest field (a new env var or OAuth setting) is inert until the catalog sync re-reads the bumped package into the database — the database catalog, not live manifests, is the runtime source.
## Where to go next
The end-to-end mental model, from a prompt or canvas to a running, observable workflow.
The two realtime planes and their event taxonomies in full.
The request lifecycle, content types, and how every operation is shown three ways.
Hosts, environments, and the no-`/v1` versioning policy.
---
# Core concepts at a glance
URL: https://docs.modulex.dev/get-started/core-concepts
A skimmable map of the ideas behind ModuleX: workflows and runs, nodes, the AI Composer, the Assistant, knowledge and RAG, credits, and organizations.
This page is a map, not a manual. It defines the words you will meet everywhere else in the docs and points you to the page that covers each one in depth. Read it top to bottom once, then come back whenever a term is unfamiliar.
If you only remember one sentence: **you build a workflow, you run it, and ModuleX meters managed usage in credits — all inside an organization.**
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1020 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** A single concept map that shows how the core ideas connect.
**[IMAGE_DETAILS]:** One illustration (not a screenshot). Center node "Organization" containing a "Workflow" made of "Nodes"; arrows out to "Run" (one execution), "AI Composer" (builds the workflow), "Assistant" (chat that uses tools), "Knowledge" (RAG), and "Credits" (meters managed usage). Label the connectors with plain verbs (builds, runs, retrieves, meters). 16:9, light theme, ModuleX brand palette, minimal text inside shapes.
## The building blocks
Start here. These four terms describe what you make and what happens when you press run.
A **workflow** is an editable graph that connects tools, data, and agents into a repeatable process. You build it on the visual canvas or generate it from a prompt with the AI Composer.
A **run** is one execution of a workflow. Each run streams its progress live and ends in a final state you can inspect. You can run from chat, the API, or an SDK.
A **node** is one step in a workflow. Every node writes its result back into the run so later steps can use it. ModuleX has nine node types.
A **reference** — written `{{node_id.field}}` — pulls a value from an earlier node into a later one. References are how data flows between steps.
### The nine node types
A workflow is assembled from a fixed set of nine **node types**. You do not need to memorize them now — each links to its own reference page.
Call a language model with a prompt and optional structured output.
Run an autonomous step that can call tools and loop until it is done.
Retrieve relevant context from a knowledge base inside a run.
Call one action from a connected integration.
Run a built-in function such as an HTTP request or a webhook.
Branch on an expression or an LLM decision, or loop over data.
Pause the run to ask a person a question, then resume with their answer.
Reshape, map, and combine data between steps.
Validate content with schema, regex, or PII checks before it moves on.
## The two AI helpers
ModuleX has two assistants, and they are easy to mix up. The short version: **the AI Composer builds workflows; the Assistant gets work done without one.**
The text-to-workflow agent. Describe what you want in plain English and the **AI Composer** turns it into a complete, editable workflow graph — then keeps editing the canvas as you chat with it.
A workflow-independent agentic chat. The **Assistant** searches your connected tools, decides the next step, calls tools, drafts outputs, and pauses for your approval before sensitive actions — no workflow required.
Use the **AI Composer** when you want a reusable process you can run again and again — for example, "every time a form is submitted, summarize it and post to Slack." The Composer produces a workflow you own and can edit on the canvas.
Use the **Assistant** for one-off or open-ended tasks where you do not want to build anything first — for example, "find the three most recent issues in this repo and draft a reply." The Assistant acts directly using your connected tools.
Both can stop and ask you for input or approval mid-task. That pause-and-resume behavior is called **human-in-the-loop**.
## Knowledge and RAG
**Knowledge** is your own content — documents, files, and data — made searchable so a workflow or the Assistant can pull in relevant context automatically. The retrieval technique behind this is **RAG** (retrieval-augmented generation).
A **knowledge base** is the unit RAG searches over. You add documents to it; ModuleX splits them into chunks and indexes them for retrieval.
Use the ModuleX-managed store (`modulexdb`), or bring your own vector store such as Qdrant, Pinecone, MongoDB Atlas, or Weaviate. Managed retrieval and ingest are billed in credits; bring-your-own stores are not.
## Connecting the outside world
A **workflow** or the **Assistant** is only as useful as what it can reach. That is what integrations are for.
An **integration** is a connector to an external service — Slack, GitHub, Google, and more. ModuleX ships **175** integrations.
A **tool** is one callable action an integration exposes (for example, "create an issue"). A single integration usually exposes many tools.
A **credential** is the stored, encrypted connection that lets ModuleX act on your behalf in an external service — for example an OAuth2 connection or an API key.
**BYOK** (bring your own key) lets you connect your own model or service accounts. Usage you bring is billed by that provider, not metered as ModuleX credits.
## How usage is paid for
Managed usage runs on **credits**. Bring-your-own-key usage does not consume credits — it is billed directly by your provider.
A **credit** is the unit that meters ModuleX-managed usage. **100 credits equal $1.00** (one credit is $0.01). Each run, managed model call, and managed retrieval consumes credits.
Your **plan** sets your monthly credit allowance and limits. The plans are **Free**, **Pro**, **Max**, and **Enterprise**.
The prepaid **wallet** covers usage beyond your plan's allowance once you turn on extra usage. Top it up manually or automatically.
Before a run, Composer turn, Assistant turn, or managed knowledge call starts, ModuleX checks that you have credit and capacity. If you do not, the request is declined with a clear billing error instead of running and failing.
The usage gate is live on the run, AI Composer, Assistant, and managed-knowledge surfaces. When it declines a request you get a `402`, `403`, or `429` response carrying a structured reason. Plain create-read-update-delete and organization-settings calls are not gated this way. See [Usage gating & limits](/billing/usage-gating) and [Errors & status codes](/api-reference/errors) for the exact shapes.
## Where everything lives: organizations
Everything in ModuleX belongs to an **organization**. It is the tenant and billing boundary — your workflows, credentials, knowledge bases, plan, wallet, and credits are all scoped to one organization.
An **organization** is the shared workspace and billing unit. People you invite become members of it, and every run is metered against its plan and credits.
Each member has a **role**. The live roles are **owner** and **admin**. Actions such as using the AI Composer, the Assistant, and schedules require owner or admin.
Earlier ModuleX had a separate "member" role. It has been **retired** — the current roles are **owner** and **admin** only. If you see "member" referenced in older material, treat it as out of date.
## Working together in real time
ModuleX is multi-user. Two things stream live, and they travel over different channels — worth knowing because the rest of the docs keep them separate.
While a run executes, its progress streams to you event by event, so you can watch each node complete in real time.
Several people can edit the same workflow canvas at once, with live cursors, presence, and locks so edits do not collide.
## Keep going
See these concepts as one end-to-end flow, from a prompt to a running, observable workflow.
Create an organization, get an API key, and make your first authenticated call.
The full canonical term list, including the exact spellings the docs standardize on.
---
# Base URLs, environments & versioning
URL: https://docs.modulex.dev/get-started/environments
The ModuleX API base URL (https://api.modulex.dev), how to point the SDKs at local or staging environments, why there is no /v1 path segment, and how the API and SDKs are versioned.
The ModuleX REST API is served from a single production base URL. There is **no `/v1` (or `/api/v1`) path segment** — routers mount directly at their resource path, so a request URL is just the base URL joined to the route (for example `https://api.modulex.dev/workflows`). This page covers the base URL, how to point each surface at a different environment, the trailing-slash rule, and how the API and the SDKs are versioned.
For how to authenticate those requests, see [Authentication](/api-reference/authentication). For the request lifecycle and content types, see the [API overview](/api-reference/overview).
## Base URL
| Environment | Base URL | Notes |
| --- | --- | --- |
| Production (default) | `https://api.modulex.dev` | The base URL every SDK uses unless you override it. |
| Local development | `http://localhost:8000` | The backend's documented local serving port. |
Both the [JavaScript SDK](/sdks/javascript) and the [Python SDK](/sdks/python) default to `https://api.modulex.dev`, so you do not set the base URL for normal use. You only override it to target a local backend or a self-hosted deployment.
The production OAuth redirect target — where a browser is sent back after connecting a credential — is the ModuleX **app** at `https://app.modulex.dev`, not the API host. The API host `https://api.modulex.dev` only serves REST endpoints and the realtime streams. See [Credentials & OAuth2](/concepts/credentials-oauth).
### How a request URL is built
The SDKs build every request URL as `baseUrl + path`, with no version segment inserted. A trailing slash on the base URL is stripped before the path is joined, so `https://api.modulex.dev/` and `https://api.modulex.dev` behave identically.
```text Request URL composition
base URL https://api.modulex.dev
+ route path /workflows/9d1f0c2e-4b7a-4c1e-8f3a-2b6d5e0a1c34/run
= request URL https://api.modulex.dev/workflows/9d1f0c2e-4b7a-4c1e-8f3a-2b6d5e0a1c34/run
```
## No `/v1` path segment
ModuleX does not put a version number in the URL path. Every resource router mounts directly at its prefix:
| Resource | Full URL |
| --- | --- |
| Workflows | `https://api.modulex.dev/workflows` |
| Run a workflow | `https://api.modulex.dev/workflows/{workflow_id}/run` |
| Knowledge bases | `https://api.modulex.dev/knowledge-bases` |
| Credentials | `https://api.modulex.dev/credentials` |
| Integrations | `https://api.modulex.dev/integrations` |
| Organizations | `https://api.modulex.dev/organizations` |
| API keys | `https://api.modulex.dev/api-keys` |
Do not prefix routes with `/v1` or `/api/v1`. There is no such segment — a request to `https://api.modulex.dev/v1/workflows` does not resolve to the workflows router. Use `https://api.modulex.dev/workflows`.
## Trailing slashes
The API has **automatic trailing-slash redirects turned off**. A route is matched exactly as declared, so request the path without a trailing slash:
| Request | Result |
| --- | --- |
| `GET /workflows` | Matches the list-workflows route. |
| `GET /workflows/` | Does **not** redirect to `/workflows`; it is treated as a different, unmatched path. |
Always call the canonical path with no trailing slash. The SDKs already do this for you.
## Switching environments
You change the environment by changing the base URL. Authentication is unchanged across environments — every request still sends `Authorization: Bearer mx_live_…` and, for organization-scoped endpoints, `X-Organization-ID`. Use a key that belongs to the environment you are calling.
```bash cURL
# Production (default)
curl https://api.modulex.dev/workflows \
-H "Authorization: Bearer mx_live_8sJ2kQ4mZ1pX7vR9tB3nW6yL0aD5cF" \
-H "X-Organization-ID: 9d1f0c2e-4b7a-4c1e-8f3a-2b6d5e0a1c34"
# Local backend — same call, base URL swapped
curl http://localhost:8000/workflows \
-H "Authorization: Bearer mx_live_8sJ2kQ4mZ1pX7vR9tB3nW6yL0aD5cF" \
-H "X-Organization-ID: 9d1f0c2e-4b7a-4c1e-8f3a-2b6d5e0a1c34"
```
```python Python
from modulex import Modulex
# Production (default) — no base_url needed
client = Modulex(
api_key="mx_live_8sJ2kQ4mZ1pX7vR9tB3nW6yL0aD5cF",
organization_id="9d1f0c2e-4b7a-4c1e-8f3a-2b6d5e0a1c34",
)
# Local backend — override base_url
local = Modulex(
api_key="mx_live_8sJ2kQ4mZ1pX7vR9tB3nW6yL0aD5cF",
organization_id="9d1f0c2e-4b7a-4c1e-8f3a-2b6d5e0a1c34",
base_url="http://localhost:8000",
)
```
```javascript JavaScript
import { Modulex } from "modulex";
// Production (default) — no baseUrl needed
const client = new Modulex({
apiKey: "mx_live_8sJ2kQ4mZ1pX7vR9tB3nW6yL0aD5cF",
organizationId: "9d1f0c2e-4b7a-4c1e-8f3a-2b6d5e0a1c34",
});
// Local backend — override baseUrl
const local = new Modulex({
apiKey: "mx_live_8sJ2kQ4mZ1pX7vR9tB3nW6yL0aD5cF",
organizationId: "9d1f0c2e-4b7a-4c1e-8f3a-2b6d5e0a1c34",
baseUrl: "http://localhost:8000",
});
```
### Configuring the base URL per SDK
The two SDKs differ in whether the base URL can come from an environment variable. This matters when you deploy the same code to different environments.
**Python SDK.** Set it explicitly on the constructor, or set the `MODULEX_BASE_URL` environment variable, or let it fall back to the default. The resolution order is **constructor argument → `MODULEX_BASE_URL` → default**. The same fallback exists for `MODULEX_API_KEY` and `MODULEX_ORGANIZATION_ID`.
**JavaScript SDK.** Set it on the constructor (`baseUrl`) or omit it for the default. The JavaScript SDK has **no environment-variable fallback** — there is no `MODULEX_BASE_URL` lookup, and likewise no env fallback for the API key or organization ID. Read any environment variables in your own code and pass the value to the constructor.
```javascript JavaScript — env-driven base URL (you read the env var)
import { Modulex } from "modulex";
// The JS SDK does not read process.env itself — pass it through explicitly.
const client = new Modulex({
apiKey: process.env.MODULEX_API_KEY ?? "",
organizationId: process.env.MODULEX_ORGANIZATION_ID ?? "",
baseUrl: process.env.MODULEX_BASE_URL ?? "https://api.modulex.dev",
});
```
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1070 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** A side-by-side diagram of base-URL resolution for the Python and JavaScript SDKs.
**[IMAGE_DETAILS]:** Two columns. Python column shows a resolution chain: `base_url` argument → `MODULEX_BASE_URL` env var → default `https://api.modulex.dev`. JavaScript column shows: `baseUrl` argument → (no env fallback) → default `https://api.modulex.dev`. Highlight in a contrasting color that JS skips the env-var step. Clean, light theme, 16:9, suitable for inline placement under the "Configuring the base URL per SDK" heading.
## Versioning
ModuleX versions the API and the SDKs separately. Neither uses a version segment in the URL path.
### API versioning
The API is **unversioned in the URL** — there is no `/v1` path segment and no API-version request header to send. The backend application advertises an internal version string of `0.1.2` (visible at the service root `GET /` and the health endpoint `GET /system/health`), but you do not pass a version on a request, and you cannot pin to a specific API version from the client side.
Because there is no version negotiation, ModuleX evolves the API in a backward-compatible way wherever possible. Track changes that affect you through the [changelog](/reference/changelog), and use the [SDK ⇄ API parity matrix](/sdks/parity) to confirm which routes a given SDK release covers.
### SDK versioning (semantic versioning)
The official SDKs follow semantic versioning and ship at version **1.0.0**:
| SDK | Package | Version | Page |
| --- | --- | --- | --- |
| JavaScript / TypeScript | `modulex` | `1.0.0` | [JavaScript SDK](/sdks/javascript) |
| Python | `modulex` | `1.0.0` | [Python SDK](/sdks/python) |
Pin the SDK version in your dependency manifest so a major release does not change behavior under you. Breaking changes land in a new major version; consult the changelog before upgrading across a major boundary. Notable changes already shipped in the 1.0 line include the retirement of the organization `member` role (invites accept only `admin`; see [Roles & permissions](/security/roles-permissions)), realtime SSE frames discriminating on `type` rather than `event`, and the removal of client-side billing helpers from the JavaScript SDK.
The Python SDK sends a `User-Agent` of `modulex-python/` on every request; the JavaScript SDK does not set a `User-Agent`. Neither identifies an API version, because the API is unversioned.
## Interactive API documentation
The running backend also serves machine- and human-readable API references at the base URL:
| Path | Surface |
| --- | --- |
| `https://api.modulex.dev/docs` | Swagger UI (interactive). |
| `https://api.modulex.dev/redoc` | ReDoc reference. |
| `https://api.modulex.dev/system/health` | Public liveness check returning `{ "status": "healthy", "service": "ModuleX", "version": "0.1.2" }`. |
For the curated, language-tabbed reference and a live "Try it" playground inside these docs, use the [API overview](/api-reference/overview) and the endpoint reference. To check live availability, see [System status & health](/reference/status).
## What does not change per environment
Switching environments changes only the base URL. The following are the same across production and a local or self-hosted backend:
Every request sends `Authorization: Bearer mx_live_…`, and organization-scoped requests also send `X-Organization-ID`. See [Authentication](/api-reference/authentication).
The same paths with no `/v1` segment, called without a trailing slash.
The same three error shapes, including the billing `DenialEnvelope` returned as 402 / 403 / 429 on metered surfaces. See [Errors & status codes](/api-reference/errors).
The same per-key, per-user, and per-organization limits and `429` responses. See [Rate limiting](/api-reference/rate-limiting).
## Next steps
Authenticate and run a workflow with cURL, Python, and JavaScript.
The `Authorization: Bearer` header and `X-Organization-ID` org context.
The request lifecycle, content types, and how each operation is shown three ways.
Which REST routes each SDK release maps to, with gaps called out.
---
# Make your first API call
URL: https://docs.modulex.dev/get-started/first-api-call
Run a ModuleX workflow programmatically and stream its result with cURL, Python, and JavaScript — authenticated with Authorization: Bearer and X-Organization-ID.
This page runs a deployed workflow from code and streams its result, end to end, in three languages. You will send one authenticated `POST` to start a run, then open a Server-Sent Events (SSE) stream to watch it finish. Every operation is shown once as a `` with cURL, Python, and JavaScript tabs.
If you have not yet created an organization and an API key, start with the [Quickstart](/get-started/quickstart) and come back here. For the full request lifecycle, base URLs, and the unified SDK reference, see the [API overview](/api-reference/overview) and the [SDKs overview](/sdks/overview).
You need a saved workflow with an **active deployment** to run it by `workflow_id`. Deploying a workflow snapshots its schema and marks one deployment live; `POST /workflows/run` loads that live snapshot. Build and deploy one first in the [workflow builder](/workflow-builder/overview), then run it here. You can also run an inline ad-hoc definition — see [Running by ID vs. inline definition](#running-by-id-vs-inline-definition).
## Before you begin
You need three things:
A user API key with the `mx_live_` prefix. Create one in the app under your organization's API Keys settings, or with `POST /api-keys`. Treat it like a password — it carries your organization's permissions.
The UUID of the organization the call runs against. Every org-scoped request requires it in the `X-Organization-ID` header. Retrieve it from `GET /auth/me` (the `primary_organization_id` field) or `GET /organizations`.
A workflow with an active deployment, identified by its `workflow_id`. If the workflow has no live deployment, `POST /workflows/run` returns `400` — deploy it first.
The base URL is `https://api.modulex.dev`. Routers mount at the root, so there is **no `/v1` or `/api` path segment** — the run endpoint is exactly `https://api.modulex.dev/workflows/run`. See [Base URLs, environments & versioning](/get-started/environments) for details.
## Authentication
Authenticate every request with two headers:
```http
Authorization: Bearer mx_live_xxx
X-Organization-ID: 11111111-1111-1111-1111-111111111111
```
The auth header is `Authorization: Bearer`, **not** `X-Authorization`. There is no `X-Authorization` header anywhere in ModuleX. The backend accepts your API key as `Authorization: Bearer mx_live_…` or, alternatively, as `X-API-KEY: mx_live_…`. Both official SDKs send the `Authorization: Bearer` form. See [Authentication](/api-reference/authentication) for the complete model.
`Bearer mx_live_`. The same scheme carries either a user API key (`mx_live_` prefix) or a Clerk JWT (browser sessions); the backend distinguishes them by the prefix. For programmatic calls, use your `mx_live_` key.
The organization UUID the request is scoped to. **Required** on org-scoped endpoints, including `/workflows/run`. If it is missing, the request fails with `400` and `{"detail": "X-Organization-ID header is required"}`.
Optional alternative to `Authorization: Bearer` for the API key. Send either one, not both. The SDKs do not use this header.
`application/json` on the `POST` body. Omit it on the SSE `GET` (the listen call has no body).
`POST /workflows/run` requires the caller to be an **owner or admin** of the organization. A non-admin caller receives `403`. The `member` role is retired and is not a current first-class role — see [Roles & permissions](/security/roles-permissions).
## Install an SDK
The cURL examples need no dependencies. To use a typed client, install one of the official SDKs.
```bash Python
pip install modulex-python
```
```bash JavaScript
npm install modulex-js
```
The Python SDK is **async-only** and reads `MODULEX_API_KEY`, `MODULEX_BASE_URL`, and `MODULEX_ORGANIZATION_ID` from the environment when the matching constructor argument is omitted. The JavaScript SDK has **no environment-variable fallback** — pass `apiKey` (and `organizationId`) to the constructor explicitly. Both default `baseUrl` to `https://api.modulex.dev`. This divergence is documented on the [JavaScript SDK](/sdks/javascript) and [Python SDK](/sdks/python) pages.
## Step 1 — Start a run
Send a `POST` to `/workflows/run` with the `workflow_id` of your deployed workflow and the `input` your workflow's state expects. The request returns immediately — the run executes in the background — so the response status is `running`, not a final result.
In the SDKs this operation is `client.executions.run(...)` (the execution-control methods live under `/workflows` on the backend but are grouped as `executions` in both clients).
```bash cURL
curl -X POST https://api.modulex.dev/workflows/run \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111" \
-H "Content-Type: application/json" \
-d '{
"workflow_id": "550e8400-e29b-41d4-a716-446655440000",
"input": { "query": "Summarize this week'\''s AI news" },
"config": { "recursion_limit": 50 }
}'
```
```python Python
import asyncio
from modulex import Modulex
async def main():
async with Modulex(
api_key="mx_live_xxx",
organization_id="11111111-1111-1111-1111-111111111111",
) as client:
run = await client.executions.run(
workflow_id="550e8400-e29b-41d4-a716-446655440000",
input={"query": "Summarize this week's AI news"},
config={"recursion_limit": 50},
)
print(run.status, run.run_id, run.thread_id)
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_xxx",
organizationId: "11111111-1111-1111-1111-111111111111",
});
const run = await client.executions.run({
workflowId: "550e8400-e29b-41d4-a716-446655440000",
input: { query: "Summarize this week's AI news" },
config: { recursionLimit: 50 },
});
console.log(run.status, run.run_id, run.thread_id);
```
In the JavaScript SDK, request parameters are **camelCase** (`workflowId`, `recursionLimit`) and are converted to snake_case on the wire — but **response fields stay snake_case** (`run.run_id`, `run.thread_id`). The Python SDK is snake_case in both directions. This is why the JS example reads `run.run_id`, not `run.runId`.
### Request body
The `/workflows/run` body is a JSON object. Provide **exactly one** execution mode (`workflow_id`, `workflow`, or `system_workflow`); the rest of the fields are optional.
The UUID of a saved workflow. ModuleX loads that workflow's **live deployment** snapshot. Returns `400` if the workflow has no active deployment. Mutually exclusive with `workflow` and `system_workflow`.
An inline ad-hoc workflow definition (a full `WorkflowDefinition`) to run without saving it first. The run is marked `is_ad_hoc=true`. Mutually exclusive with `workflow_id` and `system_workflow`.
The name of a built-in system workflow. When used, both `input` and `config` are required (`400` otherwise). Mutually exclusive with the other two modes.
The initial state passed to the workflow's entry node, keyed by your `state_schema` fields.
Per-run execution config. Recognized keys: `thread_id` (string, reuse a checkpoint thread), `recursion_limit` (integer, caps graph steps; the workflow's own default is `500`), and `batch_interval_ms` (integer, event batching cadence). When running by `workflow_id`, these merge over the deployment's stored config.
Echoed back in the response. Run events are always observed by opening the SSE stream in step 2; this flag does not toggle inline token streaming.
When `true`, the run is not attached to a chat record: `chat_id` is `null` and `thread_id` is a fresh UUID.
When `true`, scopes the created chat as private. Sent as `is_private` on the wire (`isPrivate` in the JS SDK).
Attributes an inline (`workflow`) run to a saved workflow's run history without switching to deployment-load mode.
### Response
A successful start returns `200` with the run metadata. The run is not finished — you receive identifiers to track it.
```json
{
"status": "running",
"run_id": "6a7b8c9d-1e2f-3a4b-5c6d-7e8f9a0b1c2d",
"thread_id": "550e8400-e29b-41d4-a716-446655440000",
"chat_id": "550e8400-e29b-41d4-a716-446655440000",
"ephemeral": false,
"stream": true,
"workflow_name": "Research",
"workflow_version": "1.0",
"workflow_source": "database",
"elapsed_ms": 142.7,
"human_message": { "id": "...", "role": "human", "content": {} },
"ai_message": { "id": "...", "role": "ai", "running_status": "running" },
"message": "Workflow execution started in background. Use /workflows/listen/{run_id} to track progress."
}
```
Always `"running"` on a successful start. The terminal outcome arrives over the SSE stream, not in this response.
The per-execution identifier. Use it to listen, cancel, and look up the run. This is the id you pass to `GET /workflows/listen/{run_id}`.
The LangGraph checkpoint thread. Equals `chat_id` when `ephemeral=false`. Use it for `GET /workflows/state/{thread_id}` and to resume after an interrupt.
The chat the run is attached to, or `null` for an ephemeral run.
Where the executed schema came from: `database`, `request` (inline), or `system:`.
The name of the workflow being executed.
The version label of the executed workflow.
Wall-clock time spent setting up the run before responding.
The persisted user message envelope, or `null` for an ephemeral run.
The persisted assistant message envelope (with `running_status`), or `null` for an ephemeral run.
The three identifiers above are **not interchangeable**, and ModuleX uses the word "run id" in three distinct senses. Pass the right one to each call:
- `run_id` — the per-execution id for `GET /workflows/listen/{run_id}` and `POST /workflows/cancel/{run_id}`.
- `thread_id` — the checkpoint thread for `GET /workflows/state/{thread_id}` and `POST /workflows/resume/{thread_id}`.
- The run-history **primary key** (the `id` field on a `GET /workflow-runs` row) — for `GET /workflow-runs/{run_pk}`. Passing the `run_id` there returns `404`.
See [Workflows & runs](/concepts/workflows-and-runs) for the full breakdown.
### Running by ID vs. inline definition
Most calls run a saved, deployed workflow by `workflow_id`. To run a definition without saving it, send it inline under `workflow` instead.
```bash cURL
curl -X POST https://api.modulex.dev/workflows/run \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111" \
-H "Content-Type: application/json" \
-d '{
"workflow": {
"metadata": { "name": "Ad-hoc research", "version": "1.0" },
"state_schema": { "fields": { "query": { "type": "string" } } },
"nodes": [],
"edges": [],
"entry_point": "__start__"
},
"input": { "query": "Summarize this week'\''s AI news" }
}'
```
```python Python
run = await client.executions.run(
workflow={
"metadata": {"name": "Ad-hoc research", "version": "1.0"},
"state_schema": {"fields": {"query": {"type": "string"}}},
"nodes": [],
"edges": [],
"entry_point": "__start__",
},
input={"query": "Summarize this week's AI news"},
)
```
```javascript JavaScript
const run = await client.executions.run({
workflow: {
metadata: { name: "Ad-hoc research", version: "1.0" },
state_schema: { fields: { query: { type: "string" } } },
nodes: [],
edges: [],
entry_point: "__start__",
},
input: { query: "Summarize this week's AI news" },
});
```
Inside the inline `workflow` definition, field names are already snake_case (`state_schema`, `entry_point`) in the JavaScript SDK too — only the outer parameters use camelCase. For the complete `WorkflowDefinition` contract, see [Workflow engine & nodes](/concepts/workflow-engine) and [Variables & references](/workflow-builder/variables-and-references).
## Step 2 — Stream the result
Open `GET /workflows/listen/{run_id}` to receive run events over SSE. The stream replays any buffered history first, then tails live, and closes after a terminal event (`done`, `error`, or `cancelled`). Multiple clients can listen to the same `run_id` concurrently.
In the SDKs this is `client.executions.listen(run_id)`, which yields parsed events you iterate over.
```bash cURL
curl -N https://api.modulex.dev/workflows/listen/6a7b8c9d-1e2f-3a4b-5c6d-7e8f9a0b1c2d \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111"
```
```python Python
async with client.executions.listen(run.run_id) as stream:
async for event in stream:
if event.event == "node_update":
print("node", event.data.get("node"), "→", event.data.get("output"))
if event.is_terminal:
print("finished:", event.event)
break
```
```javascript JavaScript
for await (const event of client.executions.listen(run.run_id)) {
if (event.type === "node_update") {
console.log("node", event.node, "→", event.output);
}
if (event.type === "done" || event.type === "error" || event.type === "cancelled") {
console.log("finished:", event.type);
break;
}
}
```
The two SDKs surface the event discriminator differently. The Python `SSEEvent` normalizes it to `event.event` and exposes an `is_terminal` property; the JavaScript event uses `event.type`. Both read the same underlying wire field. The Python SDK filters heartbeat frames out by default; the JavaScript SDK skips the SSE comment lines used as keepalives.
### SSE frame format
Run events are **data-only** SSE frames: each frame is `data: {json}\n\n` with **no `event:` line**. The discriminator is the `type` key inside the JSON. Here is a raw stream for a run that completes:
```text
data: {"type":"metadata","data":{"run_id":"6a7b...","thread_id":"550e...","workflow_name":"Research","workflow_version":"1.0","workflow_type":"workflow","timestamp":"2026-06-21T10:00:00.000000+00:00"}}
data: {"type":"node_update","node":"plan","output":{"messages":[{"type":"ai","content":"..."}]}}
data: {"type":"heartbeat"}
data: {"type":"node_update","node":"summarize","output":{"summary":"This week in AI: ..."}}
data: {"type":"done","data":{"message":"Workflow completed successfully"}}
```
A failed run ends with `data: {"type":"error","message":"Execution failed: "}` instead of `done`; a cancelled run ends with `data: {"type":"cancelled","data":{...}}`.
### Run event types
These are the event shapes the executor publishes on the wire. Note that some payloads are **wrapped** under a `data` key while others are **flat** alongside `type` — the table below reflects what a live client actually receives.
First frame. `data` carries `run_id`, `thread_id`, `workflow_name`, `workflow_version`, `workflow_type`, and `timestamp`.
A node produced output. Carries `node` (the node **name**) and `output` (the serialized state delta or messages). The knowledge node emits a richer `output` object with retrieval details.
A node began executing. Carries `node`, `name`, `timestamp`, and `metadata`. Emitted by some node types (for example, knowledge).
The run paused at an interrupt (human-in-the-loop) node. `data` carries `thread_id`, `message`, and an optional `resume_schema`. This event does **not** close the live stream — resume with `POST /workflows/resume/{thread_id}` to continue. See [Human-in-the-loop (HITL) resume](/realtime/hitl).
Emitted after a resume. `data` carries `run_id`, `thread_id`, `resume_value`, and `timestamp`. A resumed workflow run keeps the **same** `run_id`.
The run completed successfully. `data` is `{"message": "Workflow completed successfully"}`. Closes the stream.
The run failed. Carries a `message` string. Closes the stream.
The run was cancelled. `data` carries `run_id`, `reason`, and `cancelled_at` (or is `null` if the cancel record already expired). Closes the stream.
A `{"type":"heartbeat"}` keepalive injected after every 15 seconds of silence so a long pause does not idle-close the connection. Not a workflow event — ignore it. The SDKs handle this for you.
The durable run status uses different wording from the live stream: the SSE `done` event corresponds to the durable status `succeeded` you see later in `GET /workflow-runs`. The live status string is `completed`; the persisted status is `succeeded`.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1050 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** Sequence diagram of the first API call: client → `POST /workflows/run` → background executor → Redis → SSE `GET /workflows/listen/{run_id}` → terminal `done`.
**[IMAGE_DETAILS]:** Three lanes (Your code, ModuleX API, Background run). Show the `POST` returning `{status:"running", run_id}` immediately, the executor publishing `metadata` → `node_update` → `heartbeat` → `done` frames, and the client iterating the SSE stream until the terminal event. Label headers `Authorization: Bearer` + `X-Organization-ID` on both HTTP arrows. Landscape 16:9, light theme, neutral palette, no app chrome.
## Step 3 — Look up the run afterward
Once the stream closes, you can read the durable run record from history. List recent runs, then fetch one by its history **primary key** (the `id` field, not the `run_id`).
```bash cURL
# List recent runs for a workflow
curl https://api.modulex.dev/workflow-runs?workflow_id=550e8400-e29b-41d4-a716-446655440000&limit=10 \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111"
```
```python Python
runs = await client.executions.list_runs(
workflow_id="550e8400-e29b-41d4-a716-446655440000", limit=10
)
latest = runs.runs[0]
detail = await client.executions.get_run(latest.id) # latest.id is the PK, not run_id
print(detail.status, detail.output_summary)
```
```javascript JavaScript
const { runs } = await client.workflowRuns.list({
workflowId: "550e8400-e29b-41d4-a716-446655440000",
limit: 10,
});
const detail = await client.workflowRuns.get(runs[0].id); // runs[0].id is the PK, not run_id
console.log(detail.status, detail.output_summary);
```
Run history is grouped differently in the two SDKs: the Python SDK folds it into `client.executions` (`list_runs` / `get_run`), while the JavaScript SDK exposes a separate `client.workflowRuns` resource (`list` / `get`). Both call the same `GET /workflow-runs` routes.
## Errors
`POST /workflows/run` is a **billing-gated** surface. Besides the usual validation and auth errors, it can return a billing denial before any run is created.
### Standard errors
These use the FastAPI envelope `{"detail": ""}`.
| Status | When it happens |
| --- | --- |
| `400` | Missing `X-Organization-ID`; no execution mode supplied; running by `workflow_id` with no active deployment; `system_workflow` without `input`/`config`. |
| `401` | Missing or invalid token (`WWW-Authenticate: Bearer` is returned). |
| `403` | The caller is not an organization owner/admin. |
| `404` | The workflow (or, on listen, the run) is not found in your organization. The same `404` covers both not-found and cross-tenant access — there is no existence leak. |
| `410` | Legacy LLM-only mode (an `llm`-only body with no workflow) is removed. Use the [Assistant](/assistant/overview) instead. |
| `422` | Request validation failed (FastAPI validation array). |
| `500` | A malformed inline `workflow` schema surfaces as `500` (it is validated inside the handler, not as a typed request model), as do other unexpected failures. |
### Billing denials (the billing gate)
When your organization is over a credit, quota, or rate limit, the gate rejects the call **before any run record, chat row, or background task is created**. The response is a **flat** `DenialEnvelope` — note there is **no `detail` wrapper**:
```json
{
"code": "credit_plan_exhausted",
"layer": "credit",
"key": "credit:org:11111111-1111-1111-1111-111111111111",
"current": 5000.0,
"limit": 5000.0,
"reason": "credit_plan_exhausted"
}
```
The HTTP status is determined by the `layer`:
| `layer` | Status | `code` values |
| --- | --- | --- |
| `rate` | `429` | `rate_limit_exceeded` (also sends `Retry-After` and `X-RateLimit-*` headers) |
| `quota` | `403` | `quota_exceeded` |
| `credit` | `402` | `credit_plan_exhausted`, `upgrade_payment_failed` |
| `wallet` | `402` | `wallet_overage_disabled`, `wallet_insufficient` |
The flat `DenialEnvelope` shape is specific to billing-gated surfaces (run, composer, assistant, managed knowledge). Plain CRUD and org-settings routes do **not** return it — they return the `{"detail": …}` shape. Branch on both. The complete taxonomy of all three error-envelope shapes is on the [Errors & status codes](/api-reference/errors) page; usage limits are detailed in [Usage gating & limits](/billing/usage-gating).
In the SDKs, the Python client maps these to typed exceptions: `402` → `PaymentRequiredError` (or `CreditExhaustedError` / `WalletError` by layer), `403` → `PermissionError` (or `QuotaExceededError`), and `429` → `RateLimitError` carrying the retry headers. The JavaScript client maps `403` → `PermissionError` and `429` → `RateLimitError`; `402` falls through to the base `ModulexError`, where you can still read `code`, `layer`, and `reason`. See [SDK errors & retries](/sdks/errors-retries).
### Retries and idempotency
The SDKs retry only safe, idempotent requests (`GET`/`HEAD`) on `429`, `500`, `502`, and `503`, with backoff that honors `Retry-After`. A `POST /workflows/run` is **not** auto-retried.
The Python SDK accepts an `idempotency_key` argument and sends it as the `Idempotency-Key` header on mutating calls, but `POST /workflows/run` mints its own `run_id` server-side and does not read that header — so it is a **no-op for run de-duplication**. Do not rely on `Idempotency-Key` to prevent duplicate runs. See [SDK errors & retries](/sdks/errors-retries).
## Next steps
The full guide: authenticate, run, stream, and handle interrupts and the billing gate end to end.
The complete SSE frame format, event taxonomy, and reconnect/replay behavior.
The JavaScript and Python clients, unified by operation, with the full parity matrix.
Base URLs, the request lifecycle, content types, and how every operation is shown three ways.
---
# Run your first workflow
URL: https://docs.modulex.dev/get-started/first-workflow
Build your first ModuleX workflow with no code — describe it to the AI Composer or drag nodes onto the canvas, then run it and watch the live result stream in.
This is the fastest way to see ModuleX work end to end. You will create a workflow in the
[workflow builder](/workflow-builder/overview), run it, and watch each step report its result
live — all without writing code or touching the API.
You have two ways to build, and you can mix them:
Type what you want in plain English. The [AI Composer](/concepts/ai-composer) generates an
editable workflow on the canvas for you.
Drag [nodes](/workflow-builder/nodes/overview) onto the [canvas](/workflow-builder/canvas)
and connect them yourself. Full control, no AI.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1040 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** A complete no-code first-workflow walkthrough: open the builder, describe a workflow to the Composer, watch it build the canvas, click Run, and watch the live stream finish.
**[APP_VIDEO_DETAILS]:** Screen recording of the live ModuleX app. Start on an empty `/workflow-builder` state, create a workflow, open the Composer panel, type "Summarize the input text and post the summary to a Slack channel", show streamed build steps and the canvas filling in, then click Run and show node statuses going pending → running → completed with output. 60–90s, 16:9, dark theme, light cursor highlight, no audio narration needed.
## Before you start
Open the app and sign in. If this is your first time, create an account and an
organization — every workflow belongs to an organization.
Go to the workflow builder. If you have no workflows yet, you will see an empty state with a
**Create your first workflow** button.
Building and running workflows in the app requires an **owner** or **admin** role in your
organization. If you do not have it, ask an organization owner to grant access. See
[organizations, roles & membership](/concepts/organizations-roles).
## Option A — Describe it to the Composer
The [AI Composer](/concepts/ai-composer) turns a plain-English description into a real,
editable workflow on the canvas. It is the quickest way to get a working draft.
From the builder, create a new workflow. The right-hand panel includes a **Chat** tab — this
is the Composer.
Type a request in your own words, for example:
```text Example Composer prompt
Create a workflow that summarizes the input text and posts the summary to a Slack channel.
```
The Composer streams its work back to you: you will see it plan, add nodes, connect them, and
explain what it changed.
The Composer may pause to ask you something — for example, which option to use or to connect a
credential for an integration like Slack. Answer in the chat and it continues. This pause-and-ask
behavior is [human-in-the-loop](/concepts/ai-composer); the Composer waits for your reply before
moving on.
When the Composer finishes, its edits appear on the canvas as **pending changes**. Use **Save**
to keep them or **Revert** to roll back to the previous version. Nothing is permanent until you
save.
The Composer edits a real workflow graph, not a throwaway preview. After it finishes you can keep
refining by hand on the canvas, or ask it for more changes in the same chat. For a longer,
guided build, see [build a workflow with Composer](/guides/build-with-composer).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1041 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** The Composer generating a workflow from a single prompt and pausing once to ask the user to connect a credential.
**[APP_VIDEO_DETAILS]:** Screen recording of the live ModuleX app, focused on the builder right panel (Chat tab) and the canvas. Show the user typing a one-line prompt, streamed text and build steps, nodes appearing on the canvas, a single human-in-the-loop question card (e.g. "Connect Slack?"), the user answering, and the pending-changes Save/Revert bar appearing. 30–45s, 16:9, dark theme, no audio.
## Option B — Build it by hand on the canvas
Prefer to drive it yourself? Build directly on the [canvas](/workflow-builder/canvas).
Drag [nodes](/workflow-builder/nodes/overview) from the node dock onto the canvas. Each node is
one step. Common starting points:
Call a language model with a prompt to draft, summarize, or classify text.
Call an integration action, such as sending a Slack message or creating a record.
Retrieve relevant context from a knowledge base.
Branch the flow or loop over a list of items.
Draw an edge from the **start** marker into your first node, then connect each node to the next.
The start marker is added for you — you connect your steps to it. Every node passes its result
forward so later steps can use it.
Select a node to open the detail panel and fill in its settings — the prompt for an LLM node, the
action and inputs for a tool node, and so on. If a node needs a connected account, the builder
flags it so you can connect a [credential](/integrations/authentication) before running.
The canvas validates as you build. It will flag a node that has no path from the start marker, a node
that is missing a required credential, or a knowledge node with no query — so you can fix issues
before you run.
## Run it and watch the stream
When your workflow is ready, run it from the builder and watch each step report back in real time.
Select **Run**. If your workflow takes input, enter the values it asks for first. The builder
runs the workflow exactly as it appears on your canvas — you do not need to deploy it first to
test it.
Each node moves through **pending → running → completed** as the run progresses, and its output
appears as it finishes. Behind the scenes this is a live event stream, so you see results arrive
step by step rather than waiting for the whole run to end.
If your workflow includes an [interrupt node](/workflow-builder/nodes/interrupt), the run pauses
and asks you a question. Answer it and the run continues from where it stopped — it stays the same
run.
When the run finishes, open the node outputs to see what each step produced. The **Runs** panel
keeps a history of past runs so you can revisit any of them.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1042 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** A workflow running in the builder with node statuses updating live and outputs appearing as each step completes.
**[APP_VIDEO_DETAILS]:** Screen recording of the live ModuleX app. Click Run, enter one input value, then show nodes transitioning pending → running → completed with their output rendering in sequence, ending on a completed run and the Runs panel. 20–30s, 16:9, dark theme, no audio.
### What if a run is blocked?
Some steps use ModuleX-managed models and storage, which are metered in
[credits](/concepts/credits-billing). If your organization has run out of its plan allowance and
has no wallet balance to cover the overage, a run can be refused before it starts — you will see a
billing message instead of a run, and nothing is charged. To fix it, top up or upgrade. Learn how
this works in [usage gating & limits](/billing/usage-gating).
Using your own provider keys (BYOK) is not metered in credits. Managed models and managed knowledge
are. See [credits & the billing model](/concepts/credits-billing) for what consumes credits.
## Next steps
Learn the canvas, nodes, and controls in depth.
A full walkthrough from prompt to running workflow.
Trigger and watch a run directly inside a chat.
Do the same thing programmatically with cURL, Python, or JavaScript.
---
# Quickstart: your first authenticated API call
URL: https://docs.modulex.dev/get-started/quickstart
Create an organization, mint a mx_live_ API key, and make your first authenticated ModuleX call with Authorization: Bearer and X-Organization-ID — in cURL, Python, and JavaScript.
This guide takes you from a fresh account to your first authenticated request. You will create an [organization](/concepts/organizations-roles), mint a `mx_live_` [API key](/api-reference/authentication), and call the API three ways — with cURL, the [Python SDK](/sdks/python), and the [JavaScript SDK](/sdks/javascript).
Every ModuleX request authenticates with two pieces:
- **`Authorization: Bearer mx_live_…`** — your API key, sent as a Bearer token.
- **`X-Organization-ID: `** — the organization the request acts in, required on every organization-scoped endpoint.
The auth header is **`Authorization: Bearer`**, not `X-Authorization`. ModuleX does not recognize an `X-Authorization` header. If you are migrating from older notes or third-party snippets that use it, switch to `Authorization: Bearer`. The backend also accepts the key in an `X-API-KEY` header as an alternative, but the official SDKs always send `Authorization: Bearer`.
## Prerequisites
Sign in to the ModuleX app. On first sign-in, a personal organization is provisioned for you automatically, so you always have at least one organization to act in. You can create more from the organization switcher. Every API call is scoped to exactly one organization — see [Organizations, roles & membership](/concepts/organizations-roles).
API keys are created by a signed-in user, and they inherit that user's access. The live organization roles are **`owner`** and **`admin`** (the `member` role has been retired). You do not need to be an owner to create a personal API key, but the actions a key can perform are still gated by your role and by [usage limits](/billing/usage-gating). See [Roles & permissions](/security/roles-permissions).
For the SDK examples you need Node.js 18+ (for the JavaScript SDK) or Python 3.9+ (for the async Python SDK). For the cURL examples you only need a terminal.
## Step 1 — Create an API key
API keys are managed in the app, under your account's API keys settings. Creating a key is the only time the full secret is shown — copy it immediately and store it somewhere safe. ModuleX stores only a salted hash and a short hint (for example `mx_live_2J9vK4xM********`), so a lost key cannot be recovered and must be replaced.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1030 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The API keys settings page in the ModuleX app, mid-creation, showing the create-key dialog and a freshly generated key that is masked except for its hint.
**[SCREENSHOT_DETAILS]:** Capture the account/API-keys settings screen. Show the "Create API key" form (name field, optional organization scope, optional expiry, rate-limit field) and the success state where the full `mx_live_…` key is displayed once with a copy button. Redact the real secret. Light mode, 16:9, annotate the "copy now — shown once" callout and the masked-key hint (`mx_live_2J9vK4xM********`).
When you create a key you can set the following fields.
A human-readable label for the key (1–255 characters), for example `CI/CD` or `Production worker`. Shown in the key list to help you identify it later.
Optional. Scopes the key to a single organization that you are a member of. When set, the key can only be used with a matching `X-Organization-ID` header — any other organization returns `403`. When omitted (`null`), the key works across all organizations you belong to, and you choose the organization per request via the header.
Optional expiry timestamp. After this time the key is rejected with `401`. Omit (`null`) for a key that never expires.
Optional per-key request limit (1–1000). Defaults to `60` requests per minute. A separate per-user limit of `300` requests per minute applies across all of your keys combined.
The create response is the **only** place the full key appears.
The key's unique identifier (UUID). Use it to fetch or revoke the key later.
The label you provided.
The full secret, for example `mx_live_2J9vK4xM8nP3wQ7tR5sL1yB6cF0dG2h4vN8pX5mK9rT3wY7u`. Returned **once**, only on creation. Every other endpoint returns the masked form instead.
The first 8 characters of the random part, used to recognize the key without exposing it.
The display form, for example `mx_live_2J9vK4xM********`.
The organization the key is scoped to, or `null` for an unscoped key.
The per-key limit applied to this key.
The expiry timestamp, or `null` if the key never expires.
Whether the key is currently usable. Becomes `false` after revocation.
When the key was created (ISO 8601).
A `mx_live_` key is `mx_live_` followed by roughly 43 random Base62 characters. Treat it like a password: never commit it to source control or paste it into client-side code. Read it from an environment variable or a secrets manager instead.
## Step 2 — Find your organization ID
Every organization-scoped request needs the `X-Organization-ID` header. You can read your organizations from `GET /auth/me/organizations`, which lists each organization's `id`, `slug`, `name`, and your `role` in it. The `id` value is what goes in the header.
`GET /auth/me/organizations` is **not** organization-scoped, so it does not itself require the `X-Organization-ID` header — it returns every organization you belong to.
```bash cURL
curl https://api.modulex.dev/auth/me/organizations \
-H "Authorization: Bearer mx_live_2J9vK4xM8nP3wQ7tR5sL1yB6cF0dG2h4vN8pX5mK9rT3wY7u"
```
```python Python
import asyncio
from modulex import Modulex
async def main():
async with Modulex(api_key="mx_live_2J9vK4xM8nP3wQ7tR5sL1yB6cF0dG2h4vN8pX5mK9rT3wY7u") as client:
result = await client.auth.organizations()
for org in result["organizations"]:
print(org["id"], org["role"], org["name"])
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from 'modulex-js';
const client = new Modulex({
apiKey: 'mx_live_2J9vK4xM8nP3wQ7tR5sL1yB6cF0dG2h4vN8pX5mK9rT3wY7u',
});
const { organizations } = await client.auth.organizations();
for (const org of organizations) {
console.log(org.id, org.role, org.name);
}
```
A successful response looks like this:
```json
{
"success": true,
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"organizations": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"slug": "acme",
"name": "ACME",
"domain": "acme.modulex.dev",
"role": "owner",
"joined_at": "2026-01-01T10:00:00",
"is_default": false
}
],
"total": 1
}
```
Copy the `id` of the organization you want to work in. You will pass it as `X-Organization-ID` on every organization-scoped call.
## Step 3 — Make your first authenticated call
With your key and organization ID in hand, call an organization-scoped endpoint. `GET /organizations/llms` returns the language-model catalog for your organization, including which models have credentials connected — a good first call that exercises both the `Authorization` and `X-Organization-ID` headers.
In the SDKs you set the organization once on the client (it is sent as `X-Organization-ID` automatically) and override it per call when you need a different organization.
```bash cURL
curl https://api.modulex.dev/organizations/llms \
-H "Authorization: Bearer mx_live_2J9vK4xM8nP3wQ7tR5sL1yB6cF0dG2h4vN8pX5mK9rT3wY7u" \
-H "X-Organization-ID: a1b2c3d4-e5f6-7890-abcd-ef1234567890"
```
```python Python
import asyncio
from modulex import Modulex
async def main():
async with Modulex(
api_key="mx_live_2J9vK4xM8nP3wQ7tR5sL1yB6cF0dG2h4vN8pX5mK9rT3wY7u",
organization_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
) as client:
catalog = await client.organizations.llms()
print(catalog["active_llm_total"], "models with credentials")
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from 'modulex-js';
const client = new Modulex({
apiKey: 'mx_live_2J9vK4xM8nP3wQ7tR5sL1yB6cF0dG2h4vN8pX5mK9rT3wY7u',
organizationId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
});
const catalog = await client.organizations.llms();
console.log(catalog.active_llm_total, 'models with credentials');
```
A `200` response confirms your credentials work. If you get an error instead, jump to [Troubleshooting](#troubleshooting) below.
`GET /organizations/llms` requires the `admin` or `owner` role. If your role is not admin or owner you will get a `403` — use `GET /auth/me` (which needs no role and no organization header) to confirm authentication on its own first.
## Install the SDKs
The SDK examples above assume you have the relevant package installed.
```bash Python
pip install modulex-python
```
```bash JavaScript (npm)
npm install modulex-js
```
```bash JavaScript (pnpm)
pnpm add modulex-js
```
Both SDKs are thin, typed clients over the same REST API — every method maps to one HTTP call. The base URL defaults to `https://api.modulex.dev` and has **no version prefix**: do not append `/api` or `/v1`. See [Base URLs, environments & versioning](/get-started/environments).
### Client configuration
The two SDKs take the same options under language-idiomatic names (camelCase in JavaScript, snake_case in Python).
| Option (JS / Python) | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `apiKey` / `api_key` | string | yes | — | Your `mx_live_` key, sent as `Authorization: Bearer`. Missing → the client throws on construction. |
| `organizationId` / `organization_id` | string | no | none | Default `X-Organization-ID` for every request; overridable per call. |
| `baseUrl` / `base_url` | string | no | `https://api.modulex.dev` | API root, no version prefix. |
| `timeout` | number (ms / s) | no | `30000` ms (JS) / `30.0` s (Python) | Per-request timeout. |
| `maxRetries` / `max_retries` | number | no | `3` | Retries for transient errors (`429`, `500`, `502`, `503`) and network errors. |
**Environment-variable fallback differs by SDK.** The **Python** SDK reads `MODULEX_API_KEY`, `MODULEX_ORGANIZATION_ID`, and `MODULEX_BASE_URL` when the matching argument is omitted, so you can construct `Modulex()` with no arguments if those are set. The **JavaScript** SDK has **no** environment-variable fallback — you must pass `apiKey` explicitly; reading `process.env.MODULEX_API_KEY` yourself is just your own code, not SDK behavior. Full details: [JavaScript SDK](/sdks/javascript) and [Python SDK](/sdks/python).
Reading the key from the environment looks like this:
```python Python
import os
import asyncio
from modulex import Modulex
async def main():
# Picks up MODULEX_API_KEY and MODULEX_ORGANIZATION_ID automatically.
async with Modulex() as client:
me = await client.auth.me()
print(me["email"])
# Or pass them explicitly:
async with Modulex(
api_key=os.environ["MODULEX_API_KEY"],
organization_id=os.environ["MODULEX_ORGANIZATION_ID"],
) as client:
me = await client.auth.me()
print(me["email"])
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from 'modulex-js';
// The JS SDK has no env fallback — read process.env yourself and pass it in.
const client = new Modulex({
apiKey: process.env.MODULEX_API_KEY,
organizationId: process.env.MODULEX_ORGANIZATION_ID,
});
const me = await client.auth.me();
console.log(me.email);
```
Response fields stay **snake_case** on the wire (`active_llm_total`, `created_at`, `organization_ids`). The JavaScript SDK converts your request keys from camelCase to snake_case automatically, but it does **not** convert responses back — read response fields in snake_case in both SDKs.
## How authentication is evaluated
Understanding the order the backend checks credentials helps you read errors correctly.
The backend reads `Authorization: Bearer ` first. If the token starts with `mx_live_` it is treated as an API key; otherwise it is treated as a Clerk JWT (the app's user-login path). If no Bearer credential resolves, it falls back to the `X-API-KEY` header (which must also start with `mx_live_`). With neither present, the request is rejected with `401`.
The key is looked up by its hash and must be active and unexpired. Each request consumes from the key's per-minute limit (default `60`) and your per-user limit (`300` across all keys). Exceeding either returns `429` with `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`, and `Retry-After` headers.
For organization-scoped endpoints, the backend reads `X-Organization-ID`. A missing header returns `400`. If your key is scoped to a specific organization, the header must match that organization or you get `403`. If you are not a member of the organization in the header, you get `403`.
For the full authentication reference — including the Clerk JWT path used inside the app — see [Authentication](/api-reference/authentication) and the [JWT vs API key auth model](/security/authentication).
## Troubleshooting
No valid credential was found, or the key is wrong, revoked, or expired. Confirm you are sending `Authorization: Bearer mx_live_…` (not `X-Authorization`), that the key is copied in full, and that it has not been revoked or passed its `expires_at`. Test the key in isolation with `GET /auth/me`, which needs no organization header.
You called an organization-scoped endpoint without the `X-Organization-ID` header. Add it with an organization ID from `GET /auth/me/organizations`. In the SDKs, set `organizationId` / `organization_id` on the client or pass it per call.
Three causes share this status: the organization in `X-Organization-ID` is not one you belong to; your key is scoped to a different organization than the header; or the endpoint requires the `owner` or `admin` role and yours is lower. Verify your membership and role with `GET /auth/me/organizations`.
You exceeded the per-key (default `60`/min) or per-user (`300`/min) limit. Read the `Retry-After` header and back off; both SDKs retry `429` automatically up to `maxRetries` / `max_retries`, honoring `Retry-After`. See [Rate limiting](/api-reference/rate-limiting).
On run, Composer, Assistant, and managed-knowledge surfaces, a usage denial returns a flat envelope `{code, layer, key, current, limit, reason}` (not wrapped in `detail`). The `layer` maps to the status: `credit`/`wallet` → `402`, `quota` → `403`, `rate` → `429`. This is distinct from the plain `{"detail": "…"}` shape on standard CRUD routes. See [Errors & status codes](/api-reference/errors) and [Usage gating & limits](/billing/usage-gating).
## Next steps
Run a workflow programmatically and stream its result in cURL, Python, and JavaScript.
The complete header, token, and error reference for authenticating every request.
Base URLs, the request lifecycle, and how every operation is shown three ways.
Install and configure the JavaScript and Python SDKs once, then use them everywhere.
---
# Why ModuleX
URL: https://docs.modulex.dev/get-started/why-modulex
What makes ModuleX different: build with natural language or a visual canvas, collaborate in realtime, bring your own model keys, ground answers in your own knowledge, and connect 175 integrations.
ModuleX is an AI workflow orchestration platform. You describe a process in plain English or lay it out on a visual canvas, connect the tools you already use, and run it from chat, the API, or an SDK.
This page covers what sets ModuleX apart. For a step-by-step picture of how the pieces fit together, read [How ModuleX works](/concepts/overview).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1010 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** A positioning diagram that places ModuleX between hand-rolled LLM glue code and rigid no-code automation tools.
**[IMAGE_DETAILS]:** Three-column layout. Left column "Write it all yourself" (LLM APIs, vendor SDKs, automation glue, your own orchestration); right column "Rigid no-code tools" (fixed templates, one model, no code escape hatch); center column "ModuleX" showing the five differentiators as labeled chips (two ways to build, realtime collaboration, your own keys, your own knowledge, 175 integrations). 1600x900, light theme, no photography, ModuleX brand greys (#1A1A1A on #E8E8E8). Center column visually emphasized.
## What makes ModuleX different
Describe the workflow to the AI Composer in plain English, or build it node by node on the visual canvas. Both produce the same editable workflow graph.
Your team works on the same canvas at once, with live cursors, presence, and node locks so two people never overwrite each other.
Connect your own model and provider accounts. Providers bill you directly, with no ModuleX markup, or use ModuleX-managed models and pay in credits.
Ground answers in your company's documents. ModuleX retrieves the relevant context automatically inside chats and workflows.
Call the services you already use from any workflow or agent. The integration registry is open source, so you can read and extend it.
Official JavaScript and Python SDKs put every workflow, run, and stream behind a typed client you can embed in your own product.
## The problem ModuleX solves
If you have built with AI before, you have probably stitched together model APIs, vendor SDKs, and automation tools by hand, then written your own glue to make them run in order, retry on failure, and stream results.
No-code automation tools remove the glue, but they tend to lock you into fixed templates, a single model, and no escape hatch when you need real code.
ModuleX sits between the two. You get a visual canvas and natural-language building for the parts that should be fast, plus an API, SDKs, and a code-capable node set for the parts that need control.
## Build the way that suits the task
You do not have to pick one building style for everything.
Tell the [AI Composer](/concepts/ai-composer) what you want in plain English. It lays out the steps, tools, and logic as an editable workflow graph.
Open the [workflow builder](/workflow-builder/overview) and adjust any node directly. Composer edits and manual edits change the same graph.
Run the finished workflow from [chat](/platform/chat/workflow-run), the [REST API](/workflow-builder/execution/api-endpoint), or an [SDK](/sdks/overview), and stream the result live.
There is also an [Assistant](/concepts/assistant): an agentic chat that uses your connected tools step by step to get work done, with no workflow to set up first.
## Work together, live
Workflows are rarely a solo effort. In ModuleX, several people can edit the same canvas at the same time.
See who else is on the canvas and where their cursor is, in realtime.
When a teammate is editing a node, it locks so your changes never collide.
Edits are versioned, so the team can see what changed and roll back when needed.
For how the canvas stays in sync across collaborators, see the [realtime and collaboration model](/concepts/realtime-model).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1011 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** Two people co-editing the same workflow canvas in realtime.
**[APP_VIDEO_DETAILS]:** Screen recording of the ModuleX workflow builder split to show two browser sessions side by side. One user drags in and connects a node while the other moves a different node; show live cursors, presence avatars, and a node lock badge appearing on the node being edited. 20 to 30 seconds, 16:9, light theme, no narration, captions only. Capture in the live app.
## Your models, your keys
ModuleX works with every major AI provider, including Anthropic, OpenAI, Google, and xAI. You choose how usage is billed.
Connect your own provider accounts. The provider bills you directly with no ModuleX markup, so you keep full cost transparency.
Skip the setup and use ModuleX-provisioned providers. Managed usage is metered in [credits](/billing/credits).
## Answers grounded in your knowledge
Connect your company's documents as knowledge bases, and ModuleX retrieves the relevant context for you, inside both chats and workflows. You can use ModuleX-managed vector storage, billed in credits, or bring your own vector store.
Let ModuleX host the vector storage and retrieval. Ingest and retrieval are billed in credits.
Point ModuleX at your own Qdrant, Pinecone, MongoDB Atlas, or Weaviate.
Read more in [Knowledge & RAG](/concepts/knowledge-rag).
## Connect the tools you already use
ModuleX ships with 175 integrations you can call from any workflow or agent. The integration registry is open source, so you can read how each connector works and add your own.
See all 175 integrations grouped by category, from source control and messaging to CRMs and databases.
## Pay only for managed usage
ModuleX meters managed usage in credits. When you bring your own keys, that usage is not credited, so your provider bill stays your provider bill.
Running a workflow or an agent turn, ingesting and retrieving from a ModuleX-managed knowledge base, and calling ModuleX-managed models all consume credits. BYOK model usage is billed by your provider, not by ModuleX. See [Credits & metering](/billing/credits) for the full breakdown.
Each plan includes a monthly credit allowance. Paid plans can spend beyond it from a prepaid wallet only if you turn on overage. If you bring your own keys, model usage runs on your provider account at provider rates. See [Billing & credits overview](/billing/overview).
## Built for teams and enterprises
As your team grows, ModuleX adds the controls larger organizations need: organization roles, access control, and audit-ready usage tracking.
Single sign-on, role-based permissions, and the security posture larger teams require.
## Where to go next
The end-to-end mental model, from a prompt or canvas to a running, observable workflow.
Create an account, get an API key, and make your first authenticated call.
Build a workflow in the canvas or with the Composer, then run it from the app.
The handful of ideas you need: workflows, runs, nodes, Composer, Assistant, knowledge, and credits.
---
# Build a RAG knowledge base
URL: https://docs.modulex.dev/guides/build-a-knowledge-base
Create a knowledge base (managed modulexdb or BYOK), ingest documents through the parse-chunk-embed pipeline, and query it with vector, hybrid, or RAG-context search over the REST API and the JavaScript and Python SDKs.
This guide takes you end to end: create a [knowledge base](/concepts/knowledge-rag),
ingest your documents through the parse-chunk-embed pipeline, and query the result with
vector, hybrid, or RAG-context search — from the REST API and both SDKs. It documents
every request field, response shape, error, and credit cost so you can wire retrieval into
a workflow or an agent with no surprises.
For the conceptual model behind retrieval (knowledge bases, managed vs BYOK, ingest and
retrieval), read [Knowledge & RAG](/concepts/knowledge-rag). To manage knowledge bases in
the app instead of by API, see the [Knowledge overview](/platform/knowledge/overview).
A **knowledge base** is a `knowledge_bases` row with its own embedding and chunking
configuration — the unit that retrieval searches over. A **document** is one uploaded
file; ingest splits it into **chunks**, each carrying a vector **embedding**. The vocabulary
on this page matches the [glossary](/reference/glossary).
## Before you start
Every endpoint on this page lives under the `/knowledge-bases` router and is **org-scoped
and admin-gated**. You need:
- A ModuleX API key (`mx_live_…`). Get one from the app or see [Authentication](/api-reference/authentication).
- The **owner** or **admin** role in the organization. Every knowledge route depends on
`organization_admin_required`, so a non-admin caller is rejected with `403`. The legacy
`member` role is retired — see [Roles & permissions](/security/roles-permissions).
- The base URL `https://api.modulex.dev`. There is **no `/v1` path segment** — paths are
exactly `/knowledge-bases/...`.
Authenticate every request with two headers (the backend also accepts `X-API-KEY` as an
alternative to the bearer token):
```http
Authorization: Bearer mx_live_xxx
X-Organization-ID: org_123
```
The header is `X-Organization-ID` with a capital `ID`. It is **required** on every
knowledge endpoint except the single unauthenticated info endpoint
[`GET /knowledge-bases/info/supported-file-types`](#supported-file-types). A missing or
wrong org context resolves to a `403` (or `404` for cross-org resources). All request
bodies and responses are snake_case JSON.
## Step 1 — choose managed or BYOK
The single decision that drives cost is whether the knowledge base is **managed** or
**BYOK** (bring your own key). It is set by `embedding_config.integration_name`:
Set `integration_name` to `modulexai`. ModuleX provisions the embedding provider and
stores vectors in its managed store. **Ingest and retrieval are billed in credits.**
See [modulexdb (managed)](/integrations/knowledge-providers/modulexdb).
Point `embedding_config` at one of your own LLM-provider credentials (for example your
own OpenAI or Cohere key). **Ingest and retrieval are uncosted** by ModuleX — you pay
the provider directly. See [Knowledge providers](/integrations/knowledge-providers/overview).
Only **managed** knowledge bases (those whose `embedding_config.integration_name` is
`modulexai`) are metered. BYOK retrieval and ingest consume **no** ModuleX credits — they
are analytics-only. The credit columns throughout this page apply to managed knowledge
bases only.
If you omit `embedding_config.credential_id` entirely, ModuleX **auto-discovers** an
org credential that exposes an embedding-capable model (it looks for an `llm_provider`
credential whose integration has a model flagged `is_embedding`). If none exists, create
fails — see the errors below.
**Embedding-config key drift.** Two key conventions coexist in the backend and both are
read defensively. The model-level default uses `provider` + `model_id`; the service
default uses `integration_name` + `provider_id` + `model_id` + `credential_id`. When you
write `embedding_config`, the embed code accepts either `provider` or `provider_id`,
either `model` or `model_id`, and either `provider_credential_id` or `credential_id`.
Pick one convention and stay consistent. Managed is detected specifically on
`integration_name == "modulexai"`.
## Step 2 — create the knowledge base
`POST /knowledge-bases` creates the base and returns `201 Created`. There is **no credit
gate** on create. On success ModuleX also auto-creates a linked internal credential (the
"native KB = credential" link) so a [knowledge node](/workflow-builder/nodes/knowledge)
can reference the base, and sets `status` to `active`.
### Request fields
Display name, 1–255 characters.
Optional free-text description.
Per-knowledge-base embedding settings. Omit it to auto-discover an embedding credential
and use the defaults below.
Set to `modulexai` for a **managed** knowledge base (billed in credits). Any other
value, or a `credential_id` pointing at your own provider, makes it **BYOK**.
Embedding provider. Accepted values are `openai`, `cohere`, `azure`, and
`huggingface`, but only `openai` and `cohere` have a working embed implementation —
anything else fails ingest with an embedding error. Read as `provider` or `provider_id`.
Embedding model. Read as `model` or `model_id`.
Vector dimension, 64–4096. The chunk column is Postgres `VECTOR(1536)`; keep
ingest-time and query-time dimensions identical.
The org credential to embed with. Read as `credential_id` or `provider_credential_id`.
If omitted, ModuleX auto-discovers an embedding-capable credential.
Per-knowledge-base chunking settings used by the ingest pipeline.
One of `recursive`, `token`, or `simple`. `recursive` splits on `separators`;
`token` uses a `cl100k_base` token window; `simple` is a fixed character window.
Target chunk size, 100–4000.
Overlap between adjacent chunks, 0–500. Must be **at most 50%** of `chunk_size`,
or validation fails.
Split points for `recursive`. Default `["\n\n", "\n", " ", ""]`.
### Create a knowledge base
```bash cURL
curl -X POST https://api.modulex.dev/knowledge-bases \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: org_123" \
-H "Content-Type: application/json" \
-d '{
"name": "Product Docs",
"description": "Technical documentation",
"embedding_config": { "integration_name": "modulexai", "model_id": "text-embedding-3-small", "dimension": 1536 },
"chunking_config": { "strategy": "recursive", "chunk_size": 1000, "chunk_overlap": 200 }
}'
```
```python Python
import asyncio
from modulex import AsyncModulex
client = AsyncModulex(
api_key="mx_live_xxx",
organization_id="org_123",
)
async def main():
kb = await client.knowledge.create(
name="Product Docs",
description="Technical documentation",
embedding_config={
"integration_name": "modulexai",
"model_id": "text-embedding-3-small",
"dimension": 1536,
},
chunking_config={"strategy": "recursive", "chunk_size": 1000, "chunk_overlap": 200},
)
print(kb["id"])
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_xxx",
organizationId: "org_123",
});
const kb = await client.knowledge.create({
name: "Product Docs",
description: "Technical documentation",
embeddingConfig: { integration_name: "modulexai", model_id: "text-embedding-3-small", dimension: 1536 },
chunkingConfig: { strategy: "recursive", chunk_size: 1000, chunk_overlap: 200 },
});
console.log(kb.id);
```
The JS SDK takes camelCase method arguments but returns snake_case fields (so the response
`id`/`created_at` stay snake_case); the Python SDK is snake_case both ways. Nested config
keys like `integration_name` and `model_id` are already snake_case on both sides.
### Response (`201 Created`)
The knowledge-base UUID.
Owning organization.
Creator user id.
The auto-created internal credential that links this base to workflow nodes.
The display name.
The description, or `null`.
The resolved embedding settings.
The resolved chunking settings.
One of `active`, `processing`, `error`, `archived`. New bases are `active`.
Document count (rolled up).
Chunk count across documents.
Token count across documents.
Creation timestamp.
Last-update timestamp.
```json Example response
{
"id": "7c1e...",
"organization_id": "org_123",
"created_by_user_id": "user_456",
"credential_id": "a1b2...",
"name": "Product Docs",
"description": "Technical documentation",
"embedding_config": { "integration_name": "modulexai", "provider_id": "openai", "model_id": "text-embedding-3-small", "credential_id": "a1b2...", "dimension": 1536 },
"chunking_config": { "strategy": "recursive", "chunk_size": 1000, "chunk_overlap": 200, "separators": ["\n\n", "\n", " ", ""] },
"document_count": 0,
"total_chunks": 0,
"total_tokens": 0,
"status": "active",
"created_at": "2026-06-20T10:00:00",
"updated_at": "2026-06-20T10:00:00"
}
```
### Create errors
| Status | Condition |
| --- | --- |
| `400` | No embedding credential could be found or auto-discovered; or config validation failed (for example `chunk_overlap` over 50% of `chunk_size`). |
| `403` | Caller is not owner/admin, **or** the plan's knowledge-base quota is exhausted (`KnowledgeBaseQuotaExceededError`). |
| `422` | Pydantic validation (for example `name` outside 1–255 characters). |
| `500` | Unexpected service error. |
The knowledge-base count quota is a **plan entitlement** (`max_knowledge_bases`):
unlimited for admin and Enterprise, Max 50, Pro 3, Free uses the config default. Quota
counts **non-archived** bases — archiving a base frees a slot. Quota and storage denials
use the plain `403` `{"detail": ...}` shape, **not** the billing
[`DenialEnvelope`](/api-reference/errors).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4460 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** A diagram of the knowledge-base lifecycle: create, ingest, query.
**[IMAGE_DETAILS]:** Left-to-right flow with three labeled stages. Stage 1 "Create" box (POST /knowledge-bases, sets embedding_config + chunking_config, status active). Stage 2 "Ingest" box showing the worker pipeline parse to chunk to embed to pgvector, with a document status lane pending to processing to completed/failed. Stage 3 "Query" box listing the four search modes (vector, multi-KB, hybrid, retrieve-context) returning ranked chunks. Mark the managed credit points: 1 credit on ingest, 1 credit per retrieval, on the relevant arrows. Light theme, 16:9, clean flowchart, no UI chrome.
## Step 3 — ingest documents
Upload a file with `POST /knowledge-bases/{knowledge_base_id}/documents` as
`multipart/form-data`. The upload returns `201` with the document in `pending` status; a
background worker then runs the parse-chunk-embed pipeline asynchronously. You poll the
[document status](#poll-document-status) until it reaches `completed` or `failed`.
### Form parts
The document to ingest. Supported types: `pdf`, `docx`, `doc`, `txt`, `md`, `html`,
`csv`, `json`, `xlsx`, `pptx`. The type is resolved from the extension first, then the
MIME type.
Optional JSON **string** of arbitrary metadata. Invalid JSON returns `400` with
`{"detail": "Invalid metadata JSON"}`.
**Per-file size cap is a plan entitlement, not a fixed 50 MB.** The static info endpoint
advertises 50 MB, but the actually enforced per-file cap is your plan's storage
entitlement: Free 10 MB, Pro 50 MB, Max 100 MB, Enterprise unlimited. Plan-storage and
per-base document-count breaches return `403` `{"detail": ...}` (not the billing
envelope). The hard 50 MB constant is only a fallback when the plan does not meter file
size. A base also accepts at most 500 documents.
**Deduplication.** ModuleX computes a SHA-256 of the file. Uploading the same content to
the same base again returns `400` (`Duplicate file...`). To re-ingest changed content,
delete the existing document first.
### Upload a document
```bash cURL
curl -X POST https://api.modulex.dev/knowledge-bases/7c1e.../documents \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: org_123" \
-F "file=@manual.pdf" \
-F 'metadata={"tags":["product"]}'
```
```python Python
import asyncio
from modulex import AsyncModulex
client = AsyncModulex(api_key="mx_live_xxx", organization_id="org_123")
async def main():
with open("manual.pdf", "rb") as f:
doc = await client.knowledge.upload_document(
knowledge_base_id="7c1e...",
file=f,
metadata={"tags": ["product"]},
)
print(doc["id"], doc["status"]) # -> "pending"
asyncio.run(main())
```
```javascript JavaScript
import { readFileSync } from "node:fs";
import { Modulex } from "modulex-js";
const client = new Modulex({ apiKey: "mx_live_xxx", organizationId: "org_123" });
const doc = await client.knowledge.uploadDocument("7c1e...", {
file: new Blob([readFileSync("manual.pdf")]),
metadata: { tags: ["product"] },
});
console.log(doc.id, doc.status); // -> "pending"
```
### Upload response (`201 Created`)
The upload endpoint returns the router `DocumentResponse` shape:
Document UUID.
Parent base.
Original filename.
Resolved type (for example `pdf`).
File size in bytes.
Lifecycle status; `pending` immediately after upload.
Chunks produced; `0` until ingest completes.
Tokens counted; `0` until ingest completes.
Failure reason, or `null`.
Upload timestamp.
```json Example response
{
"id": "d1...",
"knowledge_base_id": "7c1e...",
"filename": "manual.pdf",
"file_type": "pdf",
"file_size_bytes": 820341,
"status": "pending",
"chunk_count": 0,
"token_count": 0,
"error_message": null,
"created_at": "2026-06-20T12:00:00"
}
```
### What the worker does
The background `ingest_document` task (retried up to 3 times) drives the document from
`pending` to a terminal state:
Decodes text formats; uses `pypdf` for PDF, `python-docx` for Word, and the
`unstructured` library for HTML and unknown types.
Splits text per `chunking_config`, recording `token_count`, `start_char`, and
`end_char` for each chunk.
Generates embeddings with OpenAI or Cohere. A **managed** base routes through the same
underlying model used at query time, so ingest-time and search-time vectors match.
Writes chunk rows with their vectors, sets the document `completed`, and updates
`chunk_count` and `token_count`. On any exception the document is set `failed` with an
`error_message` and the task retries.
The document status lifecycle is `pending → processing → completed | failed`, and a
`failed` document can be returned to `pending` with [retry](#retry-a-failed-document).
### Poll document status
`GET /knowledge-bases/{kb_id}/documents/{document_id}/status` returns a status dict whose
extra fields vary by state. Poll it until `status` is `completed` or `failed`.
```json Example response (completed)
{
"document_id": "d1...",
"status": "completed",
"filename": "manual.pdf",
"file_type": "pdf",
"message": "Processing completed successfully",
"processing_completed_at": "2026-06-20T12:01:30",
"chunk_count": 42,
"token_count": 18000
}
```
- `pending` — `message: "Waiting to be processed"`.
- `processing` — adds `processing_started_at`.
- `completed` — adds `processing_completed_at`, `chunk_count`, `token_count`.
- `failed` — adds `error` with the failure reason.
### Retry a failed document
`POST /knowledge-bases/{kb_id}/documents/{document_id}/retry` re-enqueues ingest. It is
valid **only** when the document status is `failed` (otherwise `400`); it resets the
document to `pending` and clears the error and timestamps. There is **no credit gate** on
retry — the per-chunk embedding cost is keyed on `{doc_id}:embedding:{token_count}`, so an
unchanged reprocess does not re-charge.
### Other document operations
| Operation | Endpoint | Notes |
| --- | --- | --- |
| List documents | `GET /knowledge-bases/{kb_id}/documents` | `status`, `limit` (1–500, default 100), `offset` query params. |
| Get a document | `GET /knowledge-bases/{kb_id}/documents/{document_id}` | Wrong-org access returns `404`, not `403`. |
| List chunks | `GET /knowledge-bases/{kb_id}/documents/{document_id}/chunks` | `limit`/`offset`; returns `{"chunks": [...], "count": N}`. |
| Delete a document | `DELETE /knowledge-bases/{kb_id}/documents/{document_id}` | `delete_file` query (default `true`). Returns `204`. |
### Ingest errors
| Status | Condition |
| --- | --- |
| `400` | Empty file, duplicate (same hash in same base), unsupported type, or bad `metadata` JSON. |
| `403` | Caller not owner/admin, plan storage cap exceeded, or per-base document cap (500) reached. |
| `402` / `429` | **Managed only** — the ingest credit gate denied the upload (see [Costs](#step-5-costs)). Returns the `DenialEnvelope`; no document is created. |
| `422` | Missing the `file` part. |
| `500` | Unexpected service error. |
## Step 4 — query the knowledge base
ModuleX offers four retrieval modes. All reserve **1 retrieval credit on a managed base**
(see [Costs](#step-5-costs)) and accept the same auth headers. Pick the mode that fits:
`POST /knowledge-bases/{kb_id}/search` — semantic (cosine) similarity over one base.
`POST /knowledge-bases/search` — the same query across several bases, merged by score.
`POST /knowledge-bases/{kb_id}/hybrid-search` — vector plus PostgreSQL keyword ranking.
`POST /knowledge-bases/{kb_id}/retrieve-context` — a single token-budgeted RAG context string.
### Vector search
The search text (minimum length 1).
Number of results, 1–50.
Cosine-similarity floor, 0.0–1.0. Computed as `1 - distance`.
Optional filter; supports `document_id` or `document_ids` to scope to specific documents.
Return chunk text in each match.
Return chunk metadata in each match.
```bash cURL
curl -X POST https://api.modulex.dev/knowledge-bases/7c1e.../search \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: org_123" \
-H "Content-Type: application/json" \
-d '{ "query": "how to install", "top_k": 5, "min_score": 0.2 }'
```
```python Python
import asyncio
from modulex import AsyncModulex
client = AsyncModulex(api_key="mx_live_xxx", organization_id="org_123")
async def main():
result = await client.knowledge.search(
knowledge_base_id="7c1e...",
query="how to install",
top_k=5,
min_score=0.2,
)
for match in result["matches"]:
print(match["score"], match["document_filename"])
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({ apiKey: "mx_live_xxx", organizationId: "org_123" });
const result = await client.knowledge.search("7c1e...", {
query: "how to install",
top_k: 5,
min_score: 0.2,
});
for (const match of result.matches) {
console.log(match.score, match.document_filename);
}
```
The query you sent.
The base searched.
The requested result count.
Number of matches returned.
Ranked matches, highest score first.
Chunk UUID.
Source document UUID.
Source filename.
Position of the chunk in its document.
Cosine similarity, 0.0–1.0.
Chunk text (when `include_content` is true).
Chunk metadata (when `include_metadata` is true).
```json Example response
{
"query": "how to install",
"knowledge_base_id": "7c1e...",
"top_k": 5,
"total_matches": 3,
"matches": [
{
"chunk_id": "c1...",
"document_id": "d1...",
"document_filename": "manual.pdf",
"chunk_index": 4,
"score": 0.83,
"content": "To install, run...",
"metadata": {}
}
]
}
```
### Multi-base search
`POST /knowledge-bases/search` runs the query across several bases and merges results by
score. It takes `knowledge_base_ids` (array of UUIDs, required), `query` (required),
`top_k` (1–50, default 5), and `min_score` (0.0–1.0, default 0.0). Bases your org cannot
access are silently skipped. The response is
`{ "query", "knowledge_bases_searched", "top_k", "total_matches", "matches" }`.
Billing reserves **one** retrieval credit if **any** queried base is managed (regardless
of ordering). One known in-code limitation: the per-base query-embedding token cost is
recorded for the **last** searched base only.
### Hybrid search
`POST /knowledge-bases/{kb_id}/hybrid-search` blends semantic similarity with PostgreSQL
full-text ranking.
The search text.
Number of results, 1–50.
Weight of the keyword score, 0.0–1.0.
Weight of the semantic score, 0.0–1.0.
Combined weighted-score floor, 0.0–1.0.
Optional document filter, as in vector search.
Each match adds `semantic_score` and `keyword_score` alongside the combined `score`, and
the response echoes `search_type: "hybrid"` and the `weights` you used.
`min_score` is **not the same scale** across modes. In vector search it is a cosine-
similarity floor; in hybrid search it is a floor on the **combined weighted** score. Tune
it per mode.
### Retrieve context (for RAG)
`POST /knowledge-bases/{kb_id}/retrieve-context` returns a single ready-to-prompt string
instead of a match array — ideal for feeding an LLM.
The search text.
Token budget for the assembled context, 100–10000.
Chunks to consider, 1–50.
Cosine-similarity floor, 0.0–1.0.
It runs the same vector search, then concatenates chunks within the token budget, each
prefixed with a `[Source: , Chunk ]` header and joined by a separator. The
response is `{ "context": "", "query": "" }`.
```bash cURL
curl -X POST https://api.modulex.dev/knowledge-bases/7c1e.../retrieve-context \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: org_123" \
-H "Content-Type: application/json" \
-d '{ "query": "how to install", "max_tokens": 2000, "top_k": 10, "min_score": 0.3 }'
```
```python Python
import asyncio
from modulex import AsyncModulex
client = AsyncModulex(api_key="mx_live_xxx", organization_id="org_123")
async def main():
result = await client.knowledge.retrieve_context(
knowledge_base_id="7c1e...",
query="how to install",
max_tokens=2000,
top_k=10,
min_score=0.3,
)
print(result["context"])
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({ apiKey: "mx_live_xxx", organizationId: "org_123" });
const result = await client.knowledge.retrieveContext("7c1e...", {
query: "how to install",
max_tokens: 2000,
top_k: 10,
min_score: 0.3,
});
console.log(result.context);
```
### Query from a workflow or agent
Inside a workflow, a [knowledge node](/workflow-builder/nodes/knowledge) retrieves from a
base by its linked credential and returns `chunks`, `context`, or `both` (set by the
node's `output_format`). The Assistant retrieves through its own `search_knowledge` tool.
Both reuse the same managed-billing path as the REST endpoints, so the credit costs below
apply identically.
### Search errors
| Status | Condition |
| --- | --- |
| `403` | Caller not owner/admin, or the base belongs to another org (`SearchAccessDeniedError`). |
| `402` / `429` | **Managed only** — the retrieval credit gate denied the call. Returns the `DenialEnvelope`. |
| `422` | Invalid body (for example empty `query`, or `top_k` out of range). |
| `500` | Embedding error (for example an unsupported provider) or search error. |
## Step 5 — costs
Cost depends entirely on the managed-vs-BYOK choice from
[Step 1](#step-1-choose-managed-or-byok). For the full credit model, see
[Credits & metering](/billing/credits); for how the gate denies calls, see
[Usage gating & limits](/billing/usage-gating).
| Operation | Managed (`modulexai`) base | BYOK base |
| --- | --- | --- |
| Create knowledge base | Free (no credit gate) | Free |
| Document ingest (per document) | **1 credit** base, reserved before the file is written, plus the per-chunk embedding token cost recorded by the worker | Uncosted |
| Vector / hybrid / retrieve-context (per call) | **1 credit** base, reserved before the embed, plus the query-embedding token cost | Uncosted |
| Multi-base search (per call) | **1 credit** if any queried base is managed | Uncosted |
| Retry a failed document | No base charge; embedding cost not re-charged for unchanged content | Uncosted |
A credit is the managed-usage unit: **100 credits = \$1.00** (1 credit = \$0.01). The
gate works **reserve → record → release**: it reserves the credit before doing the work
and records it on success, so an exhausted balance is rejected *before* any document is
written or any embedding is generated.
On a **managed** base, ingest and retrieval flow through the live billing gate. When the
balance is exhausted (or rate-limited, or the plan quota is hit), the call is denied with
the flat `DenialEnvelope` — `{code, layer, key, current, limit, reason}` — at **402**
(credit/wallet), **403** (quota), or **429** (rate). This is **not** the
`{"detail": ...}` shape used by CRUD and access errors. A `429` also carries `Retry-After`
and `X-RateLimit-*` headers. See [Errors & status codes](/api-reference/errors) for all
three error-envelope shapes.
**Knowledge-base count quota vs storage cap** are plan **entitlements**, enforced
separately from credits and returned as `403` `{"detail": ...}` — not as the billing
envelope. Counts and caps are described under [Step 2](#step-2-create-the-knowledge-base)
and [Step 3](#step-3-ingest-documents).
## Manage and clean up
| Operation | Endpoint | Notes |
| --- | --- | --- |
| List bases | `GET /knowledge-bases` | `status`, `limit`, `offset` query params. The default unfiltered listing is cached. |
| Get one base | `GET /knowledge-bases/{kb_id}` | Includes a `stats` object with a `documents_by_status` breakdown. |
| Org-wide stats | `GET /knowledge-bases/stats` | Returns base, document, chunk, token, and total-size counts. |
| Update a base | `PUT /knowledge-bases/{kb_id}` | All fields optional; configs are merged then re-validated. |
| Archive (soft delete) | `POST /knowledge-bases/{kb_id}/archive` | Sets `status` to `archived` and frees a count-quota slot. |
| Delete (hard) | `DELETE /knowledge-bases/{kb_id}` | `delete_files` query (default `true`). Cascades chunks, documents, the base, and its linked credential. Returns `204`. |
**Supported file types — no auth.** `GET /knowledge-bases/info/supported-file-types` is the
one knowledge endpoint with no authentication. It returns the 10 supported types and the
fallback `max_file_size_bytes` (52428800) / `max_file_size_mb` (50.0). Remember that the
**enforced** per-file cap is your plan entitlement, not this advertised 50 MB.
## Next steps
The conceptual model: knowledge bases, managed vs BYOK, ingest and retrieval.
Manage knowledge bases, documents, and processing in the app.
Retrieve from a base inside a workflow.
Exactly what consumes credits, and the reserve-record-release lifecycle.
---
# Build a workflow with AI Composer
URL: https://docs.modulex.dev/guides/build-with-composer
A guided walkthrough: describe the workflow you want in plain English, refine it by answering the AI Composer's questions, then run it and iterate — no node-by-node building required.
This walkthrough takes you from a blank canvas to a running [workflow](/concepts/workflows-and-runs) using the [AI Composer](/concepts/ai-composer) — without dragging a single node yourself. You describe the outcome you want in plain English, the Composer builds it, asks you a few questions along the way, and you run the result and refine it until it does what you need.
If you've never met the Composer before, the short version is this: it's an AI agent that reads your request and assembles the workflow for you, edit by edit, right on the [canvas](/workflow-builder/canvas).
Write what you want to happen, in your own words. The Composer turns it into a workflow.
The Composer pauses to ask when it needs a choice or a connection. You answer; it keeps building.
Run the workflow, see the result, and send follow-up requests until it's right.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4380 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** A full Composer build, end to end — from typing a plain-English prompt to running the finished workflow.
**[APP_VIDEO_DETAILS]:** Screen-record the workflow builder with the Composer chat tab open. Type a prompt such as "When a new lead is added, summarize it and post a short note to the #sales Slack channel". Show the Composer streaming its build steps, nodes appearing and connecting on the canvas, one inline question being answered, the save action bar, and finally a Run that streams to a completed result. 60 to 90s, 16:9, dark theme, no audio. Highlight the three beats: describe, refine, run.
## Before you start
You need only a couple of things in place. Everything else, the Composer handles.
The Composer is available to organization **owners and admins**. The previous **member** role has been retired, so any account that can open the Composer can also use it. See [Organizations, roles & membership](/concepts/organizations-roles).
The Composer runs on managed AI usage, so each turn it takes consumes [credits](/concepts/credits-billing) — one credit per turn, plus the cost of the AI model it uses. See [Credits & the billing model](/concepts/credits-billing).
You don't need any of your integrations connected up front. If a step needs a service you haven't connected yet, the Composer will pause and walk you through connecting it (see [Step 2](#step-2-refine-with-the-composers-questions)).
## Step 1: Describe the goal in plain English
Open a workflow in the [builder](/workflow-builder/overview) and switch the right-hand panel to the **chat** tab — that's the Composer. A brand-new workflow opens a fresh conversation, ready for your first request.
Then write what you want to happen. Describe the *outcome*, not the steps. You don't need to know what a "node" is or which pieces go where — that's the Composer's job.
In the message box, describe the result in your own words. For example: "Summarize new support emails and post a daily digest to Slack." Press send.
The Composer plans the workflow, then adds and connects the steps live. New nodes appear on the canvas as it works, and a build-step indicator shows how far along it is. You don't need to refresh anything.
Alongside the build, the Composer streams a plain-English summary of what it made and why, so you understand the workflow you ended up with.
### Write a request that gets good results
The clearer your request, the closer the first draft lands. A few habits help:
Say what kicks the workflow off and what it should produce. "When a form is submitted, send the answers to a Google Sheet" gives the Composer both ends to build between.
Concrete details beat vague ones. "Post to the `#support` channel" is better than "post to Slack." You can always change specifics later, but giving them up front saves a round-trip.
You don't have to capture everything in one message. Ask for a first version, look at it, then add to it. The Composer keeps working on the same canvas across the whole conversation.
If you know you want a particular tool — a spreadsheet, a chat app, a CRM — name it. The Composer looks at the [integrations](/integrations/overview) your organization has connected and picks the right tools for the job.
The Composer edits the workflow live, but its changes are held as **pending changes** until you decide what to do with them. Nothing is locked in during this step — you review and confirm later in [Step 3](#step-3-run-and-iterate).
## Step 2: Refine with the Composer's questions
The Composer doesn't guess on the decisions that matter. When it needs a choice, a piece of text, or access to a service you haven't connected, it pauses and asks you **inline in the chat**. This back-and-forth is called **human-in-the-loop** — it's how you steer the build without having to touch the canvas yourself.
While the Composer is waiting on you, the conversation stays open and nothing else changes until you respond.
The Composer offers a short list and you pick one or several — for example, which model provider a step should use.
A quick confirmation before it does something, such as approving a sensitive action while it test-builds.
A short written answer, like the exact wording of a message or the name of a channel.
If a step needs a service you haven't connected, the Composer asks you to connect it — and for services that sign in with OAuth, it picks up on its own as soon as you finish.
Most questions are optional. When the Composer can carry on without an answer, it shows a **Skip for now** action — skip it and the Composer makes a reasonable choice and keeps building.
### Two rules that keep questions tidy
Only **one question** can be open per conversation at a time, and only the **person who was asked** can answer it. If you try to send a new request while a question is still open, the Composer asks you to answer the open one first.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4390 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** A Composer human-in-the-loop question shown inline in the builder chat.
**[SCREENSHOT_DETAILS]:** Capture the Composer chat panel mid-build showing a single-choice question (for example "Which Slack channel should I post to?") with a few selectable options and a visible "Skip for now" button, with partially-built nodes on the canvas behind it. Dark theme, crop tightly to the question card.
### Connecting a service mid-build
If a step in your workflow needs a service your organization hasn't connected yet, the Composer asks for it right when it reaches that step. You connect the service from the question card, and the Composer continues from where it paused.
For services that sign in with OAuth — like Google, Slack, or GitHub — connecting opens the provider's sign-in flow in a new window. As soon as you finish signing in, the Composer **resumes on its own**: you don't have to re-send your request or restart the build.
Reconnecting an integration whose access has already **expired** can't be refreshed automatically from the app today. If a connection has lapsed, reconnect the integration rather than relying on an in-app refresh. This is a documented gap — see [Known limitations](/reference/known-limitations).
## Step 3: Run and iterate
When the Composer finishes a turn, its edits sit on the canvas as **pending changes** with an action bar. This is your checkpoint: look the workflow over before you commit to it.
The workflow shows everything the Composer built this turn. Nothing is saved yet — read through the nodes and the Composer's summary and decide whether it matches what you asked for.
**Save** keeps the changes and updates the workflow's saved snapshot — this becomes the baseline a later revert returns to. **Revert** discards this turn's edits and restores the workflow to its last saved snapshot.
Run the workflow from the builder and watch it execute live. Each step reports as it runs, so you can see what happened and where any output came from. See [Running workflows](/workflow-builder/execution/running).
If the result isn't quite right, send the Composer a follow-up request — "filter out spam before summarizing" or "post the digest at 9am instead." It works on the same canvas, and you run again to check the change.
Confirms the Composer's edits and refreshes your workflow's saved snapshot. The new baseline for the next revert.
Restores the workflow to the snapshot from before this turn and clears the pending changes — a clean undo of the Composer's latest edits.
Iterating is the whole point. Build a first version, run it, then keep refining with follow-up requests and running again. You only have to save when you're happy — until then you can revert back to your last good baseline at any time.
Each turn the Composer takes is a fresh run on managed AI usage, so it consumes [credits](/concepts/credits-billing). If your organization is out of credits or over a limit, the turn is refused **before any work begins** with a billing response — a `402`, `403`, or `429`. See [Usage gating & limits](/billing/usage-gating) and [Errors & status codes](/api-reference/errors) for what those mean and how to clear them.
## A worked example
Here's how the three steps fit together for a common task: turning new leads into a Slack note.
"When a new lead is added, write a one-line summary of who they are and post it to the #sales Slack channel."
The Composer asks which Slack workspace to use and prompts you to connect Slack if you haven't. You connect it from the question card and the Composer continues. It may also ask you to confirm the channel name — you reply `#sales`.
You save the pending changes and run the workflow with a sample lead. The Slack note arrives. The summary is a little long, so you send one more request: "make the summary shorter — one sentence max." The Composer adjusts, you run again, and you're done.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4400 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** The worked "new lead to Slack" example, including one refinement pass.
**[APP_VIDEO_DETAILS]:** Screen-record the worked example above: prompt, a Slack connect-and-continue question, save, a run that posts to Slack, then a follow-up "make it shorter" request and a second run. 45 to 60s, 16:9, dark theme, no audio. Highlight that the second request edits the same canvas rather than starting over.
## Tips for getting more out of the Composer
The Composer shows each step as it builds. If it's heading the wrong way, stop the current turn from the chat and start over with a clearer request. Stopping a turn doesn't undo edits it already made — use **Revert** for that.
When the Composer edits a workflow you're co-editing, its changes are shared with everyone in the room automatically, so your teammates see the new nodes appear just as you do. See [Canvas collaboration](/platform/collaboration/canvas).
The Composer and manual editing share the same canvas. Drag a node yourself, then ask the Composer to extend what you built — or the other way around.
Deleting nodes **one at a time** is fully supported and syncs to everyone editing with you. A multi-node bulk delete in a single action isn't handled by the realtime collaboration server today, so delete nodes individually when working with others. See [Known limitations](/reference/known-limitations).
## Next steps
The concept behind the Composer, and how it compares to the Assistant.
The hands-on reference for the Composer panel inside the canvas.
Build and run a workflow in the app, with or without the Composer.
Trigger a workflow you built and watch it run inside a chat.
---
# Connect an integration
URL: https://docs.modulex.dev/guides/connect-an-integration
Connect a third-party service to ModuleX with OAuth or your own key, then call its tool from a workflow. A step-by-step guide for connecting GitHub, Slack, and 175 other integrations.
ModuleX connects to 175 services — GitHub, Slack, Gmail, Notion, Salesforce, and many more — so your workflows can act on them: open an issue, send a message, read a row, create a contact. This guide walks you through it end to end: connect a service once, then call one of its actions from a [tool node](/workflow-builder/nodes/tool) in a workflow.
You connect a service **once**, for your whole organization. After that, every workflow and the [Assistant](/assistant/overview) can use it. For the bigger picture of what integrations are, start with the [integrations overview](/integrations/overview).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4450 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** End-to-end walkthrough: connecting GitHub with OAuth, then calling a GitHub action from a tool node in a workflow.
**[APP_VIDEO_DETAILS]:** Screen recording in the ModuleX app. Start on the integrations catalog, pick GitHub, connect it via OAuth (show the provider consent screen, then the success toast), then switch to the workflow builder, add a tool node, pick GitHub and an action, and run it. 16:9, light theme, no personal data visible. ~60 seconds. Annotate the Connect button, the consent screen, and the tool node's integration and action pickers.
## Before you start
A few things make this go smoothly.
Integrations are connected per organization, not per person. Make sure you are working in the right one — the organization switcher is in the app header.
Only an **owner** or an **admin** can connect and manage credentials for an organization. If you do not see the connect controls, ask an owner or admin to connect the service. See [roles & permissions](/security/roles-permissions).
For most services you sign in with your existing account during the connect step. Some services need an API key instead — you can paste one in.
You do not have to connect everything yourself. ModuleX offers managed keys for many services — see [Three ways to connect](#three-ways-to-connect) below — so you can try a tool before bringing your own account.
## How connecting works
Connecting a service stores a **credential**: an encrypted record that links your organization to that service. You create it once; ModuleX encrypts it, and uses it automatically every time a workflow or the Assistant calls one of that service's tools. You never paste a secret into a workflow.
Behind the scenes there are a few canonical terms worth knowing.
An **integration** is the connection to one service, for example GitHub. Each integration exposes many **tools** — the individual actions you can call, such as `github.create_issue` or `github.list_repositories`. ModuleX has 175 integrations and 600+ tools in total. Browse them in the [catalog](/integrations/catalog).
A **credential** is the encrypted, organization-scoped record that proves your identity to a service. One integration can hold more than one credential — for example a production GitHub and a test GitHub — and you mark one as the **default**.
When a tool runs and you have not picked a specific credential, ModuleX uses the one you marked as **default** for that integration. Set or change the default any time from [managing credentials](/integrations/managing-credentials).
## Three ways to connect
A service tells ModuleX which methods it supports. Most integrations offer one or more of these three. The connect screen shows you only the options that apply.
Sign in to the service and grant access — no copying secrets. This is the smoothest path and is covered step by step below. The technical details live in [integration authentication](/integrations/authentication).
Paste an API key or token you already have from the service. Usage is billed directly by the provider, with no ModuleX markup.
For supported services, use a key ModuleX provides — nothing to set up. Managed usage is metered in [credits](/billing/credits).
## Connect a service with OAuth
OAuth lets you connect by signing in to the service, instead of handling secrets yourself. The example below uses GitHub; the steps are the same for any service that offers OAuth.
In the app, go to your organization settings and open **Browse integrations**. Find the service — search by name or filter by category — and open it. See the [integrations overview](/integrations/overview) for a tour of the catalog.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4451 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The Browse integrations catalog with GitHub highlighted.
**[SCREENSHOT_DETAILS]:** Capture the Browse integrations page in the ModuleX app. Show the search box, the category filter, and a grid of integration cards. Highlight the GitHub card. 16:9, light theme, no personal data visible.
Choose **Add credential**, then pick **OAuth** as the method. Give the credential a clear name — for example `Production GitHub` — so you can tell it apart later if you connect more than one account. Turning on **Make default** lets workflows use it automatically.
ModuleX sends you to the service's own sign-in and consent screen. Review the access it asks for, then approve. This grant uses OAuth2 with PKCE, an industry-standard secure flow — you stay on the service's site to sign in, and ModuleX never sees your password.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4452 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** A third-party OAuth consent screen (for example GitHub) shown during the connect flow.
**[SCREENSHOT_DETAILS]:** Capture the provider consent screen the user sees after choosing OAuth — the authorize/approve button and the requested-permissions list. Use a generic example account, no personal data. 16:9, light theme.
After you approve, the service sends you back to ModuleX and the credential is saved automatically. You will see a success message, and the integration now shows as connected. That is it — the service is ready to use across your workflows and the Assistant.
The integration appears under your connected credentials with a name, the OAuth method, and a default badge if you set one. You are ready to [use the tool in a workflow](#use-the-tool-in-a-workflow).
### Connect with your own key instead
If a service does not offer OAuth, or you would rather bring your own account, choose **API key** (or **bearer token**) on the same connect screen and paste the value from the service. ModuleX checks the key before saving so you catch a typo early. The secret is encrypted at rest and never shown again in full — only a masked preview.
For the full list of methods a service can offer and how each is stored and resolved, see [integration authentication](/integrations/authentication).
## Use the tool in a workflow
With the service connected, you can call its actions from a workflow. The unit that does this is the [tool node](/workflow-builder/nodes/tool) — it runs one action, with parameters you control, and writes the result into your run so later steps can use it.
Open a workflow in the [workflow builder](/workflow-builder/overview) and add a **tool node** to the canvas.
In the node's detail panel, pick the connected integration (for example GitHub) and then the action you want (for example `create_issue`). ModuleX shows the credential it will use — the default for that integration unless you choose another.
Enter the action's inputs — for `create_issue`, that is the repository, the title, and the body. You can type fixed values, or pull a value from an earlier step using a `{{node_id.field}}` reference. See [variables & references](/workflow-builder/variables-and-references) for the reference syntax.
Run the workflow. The tool node calls the service, and the action's result is written into run state under the node's own id, ready for the next step. For how runs stream and how failures surface, see [running workflows](/workflow-builder/execution/running).
Want a step where the AI decides which tools to call, rather than a fixed action? Use the [agent node](/workflow-builder/nodes/agent), or let the [Assistant](/assistant/overview) use your connected tools directly in chat — no workflow required.
## Connect a service from code
You can also create a credential through the API. Authenticate every request with your API key as `Authorization: Bearer mx_live_…` plus the `X-Organization-ID` header for your organization. The example below creates an API-key credential for a service; the response masks the secret.
OAuth connections involve a browser sign-in step, so they are made in the app, not from a single API call. Use the app's connect flow for OAuth, and the API for key-based credentials.
```bash cURL
curl -X POST https://api.modulex.dev/credentials \
-H "Authorization: Bearer mx_live_yourkey" \
-H "X-Organization-ID: 8f2b1c4e-1a2b-4c3d-9e8f-7a6b5c4d3e2f" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "tavily",
"display_name": "Production Tavily",
"make_default": true,
"auth_data": { "api_key": "tvly-your-service-key" }
}'
```
```python Python
import httpx
resp = httpx.post(
"https://api.modulex.dev/credentials",
headers={
"Authorization": "Bearer mx_live_yourkey",
"X-Organization-ID": "8f2b1c4e-1a2b-4c3d-9e8f-7a6b5c4d3e2f",
},
json={
"integration_name": "tavily",
"display_name": "Production Tavily",
"make_default": True,
"auth_data": {"api_key": "tvly-your-service-key"},
},
)
resp.raise_for_status()
print(resp.json())
```
```javascript JavaScript
const resp = await fetch("https://api.modulex.dev/credentials", {
method: "POST",
headers: {
Authorization: "Bearer mx_live_yourkey",
"X-Organization-ID": "8f2b1c4e-1a2b-4c3d-9e8f-7a6b5c4d3e2f",
"Content-Type": "application/json",
},
body: JSON.stringify({
integration_name: "tavily",
display_name: "Production Tavily",
make_default: true,
auth_data: { api_key: "tvly-your-service-key" },
}),
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
```
Creating and managing credentials requires the **owner** or **admin** role. A request from a non-admin member is rejected. ModuleX never reads the organization from the request body — it always comes from the `X-Organization-ID` header.
For the full credential API — listing, setting a default, testing, and deleting — see [managing credentials](/integrations/managing-credentials).
## Keep a connection working
A connection lasts until the service's access expires or is revoked. For OAuth connections, ModuleX refreshes access automatically in the background as tokens near expiry, so most connections keep working without any action from you.
If an OAuth connection stops working — for example because access was revoked on the service — **reconnect it** rather than looking for a manual "refresh" button. Connect the service again with OAuth, and set the new credential as the default. A manual one-click OAuth refresh in the app is a [known limitation](/reference/known-limitations) and should not be relied on.
To rotate a key-based credential, connect the service again with the new key, mark it as the default, and delete the old one. See [managing credentials](/integrations/managing-credentials).
## What it costs
How a connected service is billed depends on which method you used to connect it.
Usage is billed directly by the service provider, with no ModuleX markup. It is not metered in ModuleX credits.
Tool calls made through a ModuleX-managed key are metered in [credits](/billing/credits). When your plan's allowance runs out, calls are subject to the usage gate — see [usage gating & limits](/billing/usage-gating).
## Troubleshooting
Connecting integrations requires the **owner** or **admin** role for the organization. Switch to the correct organization in the header, or ask an owner or admin to connect the service. See [roles & permissions](/security/roles-permissions).
Start the connection again from the catalog. The sign-in step is time-limited, so if you waited too long on the consent screen, the attempt expires and you simply retry. If the service reports that access was denied, approve the requested permissions when prompted.
Double-check you copied the full key from the service, with no extra spaces, and that it has the permissions the action needs. ModuleX tests a key before saving, so a rejection here means the service did not accept it.
Confirm the credential was saved in the **same organization** you are building the workflow in, and that the integration shows as connected. If you connected more than one account, check which credential is set as the default.
Tools that use a ModuleX-managed key consume [credits](/billing/credits). If your plan's allowance is exhausted, the run is stopped by the usage gate. See [usage gating & limits](/billing/usage-gating) and [errors & troubleshooting](/help/errors-troubleshooting).
## Next steps
What integrations are, how the catalog is organized, and how to browse 175 services.
The full reference for calling one integration action from a workflow.
List, set defaults for, test, and delete the credentials your organization has connected.
The connect methods a service can offer and how each secret is stored and resolved.
---
# Realtime collaboration walkthrough
URL: https://docs.modulex.dev/guides/realtime-collaboration
A hands-on walkthrough: invite a teammate to your organization, co-edit the same workflow canvas live with presence and node locks, and resolve an edit conflict the way ModuleX does it for you.
This walkthrough takes you through building together in ModuleX from end to end: you invite a teammate into your organization, you both open the same workflow, you co-edit it live, and you watch ModuleX handle an edit conflict on its own. By the end you will know what every cursor, avatar, and badge on the canvas means.
It is the practical, do-it-yourself companion to two reference pages. For the product tour of what co-editing looks like, see [Canvas collaboration](/platform/collaboration/canvas). For the wire-level detail behind presence, locks, and the conflict model, see [Presence, locks & versioning](/realtime/presence-locks).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4410 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** The full walkthrough end to end: invite a teammate, both open the same workflow, co-edit live, then a conflict resolves itself.
**[APP_VIDEO_DETAILS]:** Screen recording with two browser sessions side by side, User A "Ada" and User B "Lin". Show, in order: Ada inviting Lin by email from organization settings; Lin opening the invitation link and accepting; both opening the same workflow; Lin's presence avatar and colored cursor appearing on Ada's canvas; Lin moving a node and it sliding into place on Ada's side; Lin opening a node so a "being edited by Lin" badge shows on Ada's side; Ada trying the same node and seeing it held; then a brief conflict toast on Ada's side that reloads to the latest version. End on both avatars in the top corner. 16:9, light theme, ~60s, annotate the invite email field, the presence avatars, the colored cursor, the editing badge, and the conflict toast.
## What you will do
Add a person to your organization by email so they can open the same workflows you can.
You and your teammate both open one workflow in the builder and join the same live canvas.
Move nodes, add steps, and edit configuration while seeing each other's cursors and node locks in realtime.
Watch what happens when two edits collide, and learn how ModuleX reconciles them for you.
## Before you start
You invite teammates into an [organization](/concepts/organizations-roles). Only an organization **owner** or **admin** can send invitations.
Have at least one workflow saved in the [Workflow Builder](/workflow-builder/overview). Everyone in the organization can open it.
You invite by email address. Your teammate signs in (or signs up) with that email to accept.
To see live co-editing yourself, open the workflow in two windows signed in as two different people.
## Step 1 — Invite a teammate
People collaborate inside an **organization**. Adding a teammate to your organization is what gives them access to your shared workflows.
Go to your organization settings and open the members area. You see this only if you are an **owner** or **admin** of the organization.
Enter your teammate's email address and send the invitation. New teammates are added with the **admin** role.
ModuleX organizations have two roles: **owner** and **admin**. The older `member` role has been retired, so an invited teammate joins as an admin. See [Roles & permissions](/security/roles-permissions) for what each role can do.
Your teammate opens the invitation link and accepts it while signed in with the invited email address. If they are not signed in yet, the link prompts them to sign in or sign up first, then completes the acceptance.
Acceptance is tied to the invited email address. If your teammate is signed in with a different account, ModuleX tells them which account the invitation was sent to so they can switch to the right one and try again.
After accepting, your teammate selects the organization from the organization switcher. Everything they do from then on is scoped to that organization, and your shared workflows become visible to them.
A freshly accepted role can take up to a few minutes to take effect on the live collaboration server, which caches membership briefly. If a brand-new teammate cannot edit immediately, have them refresh after a minute.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4411 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The organization members screen with the invite-by-email field.
**[SCREENSHOT_DETAILS]:** Capture the organization settings members area showing the email input used to invite a teammate, the role label (admin), and the list of existing members with their roles. Light theme, redact any real email addresses. Highlight the email field and the send-invitation button.
## Step 2 — Open the same workflow
Now both of you open the same workflow so you share one live canvas.
Each person opens the workflow from the [Workflow Builder](/workflow-builder/overview) list. Opening a workflow joins you to its live collaboration room automatically — there is no separate "start collaborating" button.
When your teammate joins, their **presence avatar** appears in the canvas, and you appear on theirs. Each person is assigned a color that is used consistently for their avatar, their cursor, and any node they are editing.
You do not save and reload to see each other's work. Everyone is editing the **same live graph**, so changes appear as they happen. There are no separate copies to merge later. For the full picture of the two realtime planes (live canvas editing versus run streaming), see [Realtime & collaboration model](/concepts/realtime-model).
## Step 3 — Co-edit live
With both of you in the same workflow, you can build together. Here is what you will see, and what each signal means.
### Presence and cursors
Everyone currently in the workflow shows up as a colored avatar. When someone leaves or closes the tab, their avatar disappears.
You see your teammate's cursor move across the canvas in their assigned color, so you always know where their attention is.
If a teammate stops interacting for a while, they are shown as **Away** rather than dropping off entirely. They come back to active as soon as they interact again.
A person's color is the same for their avatar, cursor, and edit badge, so it is easy to tell at a glance who is doing what.
### Editing nodes safely with locks
To stop two people from editing the same node at the same instant, ModuleX uses **node locks**.
When you open a node in the [Detail Panel](/workflow-builder/canvas) to change its configuration, ModuleX claims a lock on that node for you.
While you hold the lock, your teammates see that node marked as being edited by you, in your color. If they try to open it, ModuleX tells them who is currently editing it instead of letting them collide with you.
Your lock releases when you finish editing the node. It also releases automatically if you leave the workflow or disconnect, and it expires on its own after a few minutes of being held, so a node never stays stuck if someone closes their laptop mid-edit.
Locks apply to **editing one node's configuration**. Moving nodes around the canvas, adding new nodes, and connecting edges are not locked — those changes simply broadcast to everyone live. The lock exists to protect the inside of a node while one person has it open.
### What broadcasts live
Most edits flow to everyone in the room as you make them:
A node your teammate adds appears on your canvas moments later, already in place.
Dragging a node to a new position updates it for everyone, so the layout stays in sync.
New edges between nodes show up for the whole room as they are drawn.
Configuration changes save to the shared workflow and reach your teammates once the editor finishes with the node.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4412 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** Two teammates co-editing one canvas, showing cursors, a node move, and a node lock.
**[APP_VIDEO_DETAILS]:** Side-by-side recording of Ada and Lin in the same workflow. Show Lin's colored cursor moving on Ada's canvas, Lin adding and moving a node that appears on Ada's side, then Lin opening a node so a colored "being edited by Lin" badge shows on Ada's canvas, and Ada hovering the same node to see it is held. 16:9, light theme, ~25s, annotate the cursor, the moved node, and the editing badge.
## Step 4 — Resolve a conflict
Because everyone edits the same live graph, ModuleX keeps every collaborator on the same version. Most of the time this is invisible — edits stream back and forth and stay in order. Occasionally two people make changes so close together, or one person's connection lags far enough behind, that their version of the workflow has drifted from the shared one. That is a **conflict**, and ModuleX resolves it for you.
### What you will see
The person whose edits fell behind sees a brief notice that their changes conflicted and the workflow is reloading.
ModuleX pulls the current shared version of the workflow and shows it. The other collaborators are unaffected — they keep working.
After the reload, both people are looking at the same up-to-date graph, and editing continues normally.
You do not resolve a conflict by hand and there is no "accept mine / accept theirs" prompt. ModuleX always reconciles by reloading the behind collaborator to the latest shared version. The reliable way to avoid losing in-progress edits to a single node is to use the node lock: hold the node while you edit it, and your teammates will not edit it underneath you.
ModuleX tracks a version number for the live workflow and advances it on every accepted edit. If a collaborator's edits arrive while their version has drifted too far behind the shared one, ModuleX cannot safely apply them in place, so it reloads that person to the current version rather than risk applying a stale change. Locking a node before you edit its configuration keeps your work safe while you have it open. The exact version and conflict mechanics are documented on [Presence, locks & versioning](/realtime/presence-locks).
### Changes from Composer or the API
Not every change to a workflow comes from a person dragging nodes. The [AI Composer](/workflow-builder/composer) can rewrite the graph, and so can changes made elsewhere. When that happens while you have the workflow open, those edits **sync into your open canvas live** so you are always looking at the current version — you do not have to reload to pick them up. See [Realtime co-editing & external sync](/workflow-builder/realtime-coediting) for how that external sync works.
## A few things to know
No. Live co-editing happens entirely inside the ModuleX web app, which signs you in with your account session. There is no REST endpoint or SDK method for presence, cursors, or locks — they exist only on the live collaboration connection the app makes for you. API keys (`mx_live_*`) are for running workflows programmatically; see [Authentication](/api-reference/authentication).
Everyone in your organization who opens the same workflow joins the same live room and can edit together. There is no separate per-workflow collaborator list — organization membership is what grants access.
Any node locks you hold are released automatically when you leave the workflow or disconnect, and they also expire on their own after a few minutes. A node never stays locked because someone walked away.
The live collaboration server caches organization membership for a short time. A brand-new teammate may need to wait a minute and refresh before their edit access takes effect. See [Account & access — Help](/help/account-access).
## Where to go next
The product tour of what co-editing looks and feels like.
The wire-level reference: every event, payload, timing, and edge case.
Go from a plain-English prompt to a running workflow.
---
# Run a workflow (REST + SDK)
URL: https://docs.modulex.dev/guides/run-a-workflow
Authenticate, trigger a workflow run, and stream its result over SSE with cURL, the Python SDK, and the JavaScript SDK — including the live billing-gate responses.
This guide takes you end to end: authenticate a request, start a workflow run with `POST /workflows/run`, and stream its events over Server-Sent Events (SSE). Every operation is shown three ways — cURL, Python, and JavaScript — so you can wire it into a script or a server in minutes.
A run is asynchronous. The run endpoint returns immediately with a `run_id` while the workflow executes in the background; you then open an SSE stream on that `run_id` to watch nodes execute and receive the final result. For the full event taxonomy and frame format, see [SSE run streaming](/realtime/sse-streaming). For base URLs, the request lifecycle, and how operations map across surfaces, see the [API overview](/api-reference/overview).
**Before you start**, you need three things: an `mx_live_*` API key, your organization ID, and a workflow with an active deployment (or an inline workflow definition). API keys are created in the dashboard at `https://app.modulex.dev`; see the [Quickstart](/get-started/quickstart) and [Authentication](/api-reference/authentication).
## Prerequisites
| Requirement | Where it comes from | Notes |
| --- | --- | --- |
| API key (`mx_live_*`) | Dashboard → API keys | Sent as `Authorization: Bearer mx_live_…`. See [Authentication](/api-reference/authentication). |
| Organization ID | Dashboard, or `GET /organizations` | Sent as the `X-Organization-ID` header. Required on every org-scoped route. See [Org context](/security/org-context). |
| A runnable workflow | A deployed workflow ID, **or** an inline definition | A saved `workflow_id` must have an active deployment, or the run returns `400`. See [Deploy & versions](/workflow-builder/execution/deploy). |
| Role | `owner` or `admin` | All `/workflows` routes require an org owner or admin. The `member` role is retired. See [Roles & permissions](/security/roles-permissions). |
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4440 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The dashboard API keys screen with a freshly created `mx_live_` key and the organization ID visible.
**[SCREENSHOT_DETAILS]:** Capture the API keys settings page at `app.modulex.dev`. Show the create-key dialog with the one-time secret masked except the `mx_live_` prefix, and highlight where the organization ID is displayed. Light theme, 16:9, annotate the two values a developer copies into the examples below.
## Step 1 — Authenticate
Every request carries two headers. This is the same scheme across REST, the Python SDK, and the JavaScript SDK — there is no `X-Authorization` header.
`Bearer mx_live_…` — your API key. The backend also accepts the key in an `X-API-KEY` header, but `Authorization: Bearer` is the documented form. A missing or invalid token returns `401` with a `WWW-Authenticate: Bearer` header.
The organization (tenant) the run belongs to. Required on every org-scoped route. If it is missing, the request returns `400` with `{"detail": "X-Organization-ID header is required"}`.
`application/json` for the `POST /workflows/run` body.
The SDKs take the key and organization ID once, at construction, and attach both headers to every call. The Python SDK additionally falls back to the `MODULEX_API_KEY`, `MODULEX_BASE_URL`, and `MODULEX_ORGANIZATION_ID` environment variables; the JavaScript SDK has **no** environment-variable fallback — you must pass the values to the constructor. See the [JavaScript SDK](/sdks/javascript) and [Python SDK](/sdks/python) pages for the full configuration surface.
```bash cURL
# Reused by every request below. The base URL has no /v1 path segment.
export MODULEX_API_KEY="mx_live_xxx"
export MODULEX_ORG_ID="11111111-1111-1111-1111-111111111111"
export MODULEX_BASE_URL="https://api.modulex.dev"
# Sanity check: confirm the key + org resolve.
curl "$MODULEX_BASE_URL/auth/me" \
-H "Authorization: Bearer $MODULEX_API_KEY" \
-H "X-Organization-ID: $MODULEX_ORG_ID"
```
```python Python
import asyncio
from modulex import Modulex
client = Modulex(
api_key="mx_live_xxx",
organization_id="11111111-1111-1111-1111-111111111111",
# base_url defaults to https://api.modulex.dev
)
async def main():
me = await client.auth.me()
print(me["user_id"])
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from 'modulex-js';
const client = new Modulex({
apiKey: 'mx_live_xxx',
organizationId: '11111111-1111-1111-1111-111111111111',
// baseUrl defaults to https://api.modulex.dev
});
const me = await client.auth.me();
console.log(me.user_id);
```
## Step 2 — Start the run
Send `POST /workflows/run`. The endpoint admits the run through the billing gate, returns a `200` with run metadata, and executes the workflow in a background task. Pick exactly one execution mode.
### Execution modes
Run a saved workflow. The backend loads the schema from the workflow's **active deployment** snapshot. If the workflow has no live deployment, the run returns `400` (`Workflow has no active deployment. Deploy the workflow first…`). Request `input` overrides the deployment default; request `config` merges over the deployment config.
Run an inline, ad-hoc [`WorkflowDefinition`](/concepts/workflow-engine) without saving it. Sets `is_ad_hoc: true` on the run record. Use `attribution_workflow_id` to make an ad-hoc run appear in a saved workflow's Runs panel without switching to deployment-load mode.
Run a built-in system workflow by name. In this mode, both `input` and `config` are **required** (otherwise `400`). Exposed by the Python SDK and cURL; the JavaScript SDK does not surface this mode.
There is no LLM-only run mode. A request that carries only an `llm` config (no `workflow`, `workflow_id`, or `system_workflow`) returns `410 Gone`. Use the [Assistant](/assistant/overview) instead — `POST /assistant/chat`, documented in [Streaming responses](/assistant/streaming).
### Other body fields
State input values passed to the workflow's entry node. Keys match your workflow's `state_schema`. Required for `system_workflow` mode.
Runtime overrides for this execution. Recognized keys: `thread_id`, `recursion_limit`, and `batch_interval_ms`. Required for `system_workflow` mode.
Echoed back in the response. Run events are always consumed by opening the SSE stream in Step 3; this flag does not change that.
When `true`, no chat record is created, `chat_id` is `null`, and `thread_id` is a fresh value. When `false`, `thread_id` equals `chat_id` (the same UUID).
When `true`, the run and its messages are visible only to the creator.
For ad-hoc (inline) runs, the saved workflow to attribute this run to in run history.
The Python SDK accepts an `idempotency_key` argument on `executions.run(...)`. It is sent as an `Idempotency-Key` header, but `POST /workflows/run` mints its own `run_id` and does **not** read that header — so it is a no-op for run deduplication. The JavaScript SDK does not send it. See [SDK errors & retries](/sdks/errors-retries).
### Request
```bash cURL
# Run a saved, deployed workflow.
curl -X POST "$MODULEX_BASE_URL/workflows/run" \
-H "Authorization: Bearer $MODULEX_API_KEY" \
-H "X-Organization-ID: $MODULEX_ORG_ID" \
-H "Content-Type: application/json" \
-d '{
"workflow_id": "550e8400-e29b-41d4-a716-446655440000",
"input": { "query": "AI trends" },
"config": { "recursion_limit": 50 }
}'
```
```python Python
run = await client.executions.run(
workflow_id="550e8400-e29b-41d4-a716-446655440000",
input={"query": "AI trends"},
config={"recursion_limit": 50},
)
print(run.status, run.run_id) # "running" 6a7b8c9d-...
```
```javascript JavaScript
const run = await client.executions.run({
workflowId: '550e8400-e29b-41d4-a716-446655440000',
input: { query: 'AI trends' },
config: { recursion_limit: 50 },
});
console.log(run.status, run.run_id); // "running" 6a7b8c9d-...
```
The JavaScript SDK takes camelCase parameter names (for example `workflowId`) and converts them to snake_case on the wire — but **responses stay snake_case** (`run.run_id`, `run.thread_id`). The Python SDK is snake_case in both directions.
### Response
A `200` is returned immediately while the workflow runs in the background. The status here reflects only the synchronous portion — it is `running`, never a terminal status. Terminal outcomes arrive on the SSE stream (Step 3) or via run history (Step 5).
```json 200 — run started
{
"status": "running",
"run_id": "6a7b8c9d-1e2f-3g4h-5i6j-7k8l9m0n1o2p",
"thread_id": "550e8400-e29b-41d4-a716-446655440000",
"chat_id": "550e8400-e29b-41d4-a716-446655440000",
"ephemeral": false,
"stream": true,
"workflow_name": "Research",
"workflow_version": "1.0",
"workflow_source": "database",
"elapsed_ms": 142.7,
"human_message": { "id": "...", "role": "human", "run_id": "...", "running_status": null },
"ai_message": { "id": "...", "role": "ai", "run_id": "...", "running_status": "running" },
"message": "Workflow execution started in background. Use /workflows/listen/{run_id} to track progress."
}
```
Always `running` for a started run. Terminal status is observed via the stream or run history.
The per-execution identifier you pass to `GET /workflows/listen/{run_id}`. This is also the durable run identifier reused on resume. It is **not** the run-history primary key — see [Workflows & runs](/concepts/workflows-and-runs) for the three distinct run-id identities.
The LangGraph checkpoint thread. Equals `chat_id` when `ephemeral` is `false`. Used by `GET /workflows/state/{thread_id}` and `POST /workflows/resume/{thread_id}`.
The chat record for this run, or `null` when `ephemeral` is `true`.
Origin of the executed definition: `database`, `request`, or `system:`.
The persisted human message, or `null` for ephemeral runs (or if chat creation failed).
The persisted AI message stub (`running_status: "running"`), or `null` for ephemeral runs.
### Run errors
Missing `input`/`config` for `system_workflow` mode; a `workflow_id` with no active deployment; or no execution mode supplied. Shape: `{"detail": ""}`.
The system workflow file does not exist, or the `workflow_id` is not in your organization. Cross-tenant IDs return `404` (not `403`), so they do not leak existence. Shape: `{"detail": "..."}`.
An `llm`-only request — LLM mode was removed. Use `POST /assistant/chat`.
Billing gate denial. See [Handle the billing gate](#step-4-handle-the-billing-gate) below — these responses are live on this route.
Wrapped failure (`{"detail": "Failed to start workflow: …"}`). Because the run body is an untyped object, a malformed inline `workflow` schema also surfaces as `500` rather than `422`.
## Step 3 — Stream the run
Open `GET /workflows/listen/{run_id}` to receive run events over SSE. The stream is **data-only**: each frame is `data: \n\n` with **no** `event:` line. The event type is the `type` key inside the JSON. On (re)connect, the buffered run history (1-hour TTL) is replayed in order first, then the live tail — so reconnecting mid-run is replay-safe.
An ownership guard runs before the stream opens; an unknown or cross-tenant `run_id` returns `404` `{"detail": "Run not found"}` as a normal HTTP response (not an in-stream frame). The full frame format, reconnection, and heartbeat mechanics live on [SSE run streaming](/realtime/sse-streaming).
```bash cURL
# -N disables buffering so frames arrive as they are emitted.
curl -N "$MODULEX_BASE_URL/workflows/listen/6a7b8c9d-1e2f-3g4h-5i6j-7k8l9m0n1o2p" \
-H "Authorization: Bearer $MODULEX_API_KEY" \
-H "X-Organization-ID: $MODULEX_ORG_ID"
```
```python Python
# executions.listen() yields the parsed data object of each frame.
async for event in client.executions.listen(run.run_id):
etype = event.get("type")
if etype == "node_update":
print("node:", event.get("node"))
elif etype == "done":
print("done:", event["data"]["message"])
break
elif etype == "error":
print("error:", event.get("message"))
break
```
```javascript JavaScript
// listen() is an async generator yielding each frame's parsed data.
for await (const event of client.executions.listen(run.run_id)) {
if (event.type === 'node_update') {
console.log('node:', event.node);
} else if (event.type === 'done') {
console.log('done:', event.data.message);
break;
} else if (event.type === 'error') {
console.log('error:', event.message);
break;
}
}
```
### Event types on this stream
Document the **wire** shapes below — they are what a live client receives. The typed event models and generated TypeScript types describe a different, stale shape (for example, a typed `node_update` uses `node_id`/`status`, but the wire frame uses `node`/`output`).
First frame. `data: {run_id, thread_id, workflow_name, workflow_version, workflow_type, timestamp}`.
Emitted as each node produces output. Flat shape: `{type, node, output}` where `node` is the node **name** and `output` is the serialized state delta.
Emitted by some nodes (for example, the knowledge node) before they run: `{type, node, name, timestamp, metadata}`.
The workflow hit an interrupt (HITL) node and is awaiting input. The stream stays **open**. `data: {thread_id, message, data, resume_schema?}`. Resume with `POST /workflows/resume/{thread_id}` — see [Step 5](#step-5-optional-resume-an-interrupt-and-read-history) and [Human-in-the-loop resume](/realtime/hitl).
Published after a resume; the run continues under the **same** `run_id`. `data: {run_id, thread_id, resume_value, timestamp}`.
A `{"type": "heartbeat"}` keepalive emitted after 15 seconds of silence so a long interrupt pause does not idle-close the connection. Treat it as a no-op.
Terminal. `data: {message: "Workflow completed successfully"}`. Closes the stream.
Terminal. Flat shape: `{type, message}` (for example, `Execution failed: …`). Closes the stream.
Terminal. `data: {run_id, reason, cancelled_at}` (or `data: null` if the cancel blob already expired). Closes the stream.
The durable status string differs from the live event. The SSE `done` event corresponds to a durable run status of `succeeded` (not `completed` or `done`) when you read it back from run history in Step 5.
### Raw frame trace
A run that hits an interrupt, is resumed, then completes looks like this on the wire (no `event:` lines):
```text Wire frames
data: {"type":"metadata","data":{"run_id":"6a7b...","thread_id":"550e...","workflow_name":"Research","workflow_version":"1.0","workflow_type":"workflow","timestamp":"2026-06-21T10:00:00.000000+00:00"}}
data: {"type":"node_update","node":"plan","output":{"messages":[{"type":"ai","content":"..."}]}}
data: {"type":"heartbeat"}
data: {"type":"interrupt","data":{"thread_id":"550e...","message":"Approve this plan?","data":{},"resume_schema":{"type":"object","properties":{"approved":{"type":"boolean"}}}}}
data: {"type":"resumed","data":{"run_id":"6a7b...","thread_id":"550e...","resume_value":{"approved":true},"timestamp":"2026-06-21T10:00:30.000000+00:00"}}
data: {"type":"node_update","node":"summarize","output":{"summary":"..."}}
data: {"type":"done","data":{"message":"Workflow completed successfully"}}
```
## Step 4 — Handle the billing gate
Managed runs pass through a billing admission gate **before** any database write. On denial, the run is rejected with no run record and no background task, and the response is a flat `DenialEnvelope` — **not** the `{"detail": …}` shape. The envelope has no `detail` wrapper:
```json DenialEnvelope (402 example)
{
"code": "credit_plan_exhausted",
"layer": "credit",
"key": "credit:org:...",
"current": 1000.0,
"limit": 1000.0,
"reason": "credit_plan_exhausted"
}
```
The `layer` field maps to the HTTP status:
| `layer` | Status | `code` values | Meaning |
| --- | --- | --- | --- |
| `rate` | `429` | `rate_limit_exceeded` | Run rate limit hit. Carries `Retry-After` and `X-RateLimit-*` headers. |
| `quota` | `403` | `quota_exceeded` | A plan quota was exceeded. |
| `credit` | `402` | `credit_plan_exhausted`, `upgrade_payment_failed` | Plan credit allowance exhausted with no wallet overage, or an upgrade charge failed. |
| `wallet` | `402` | `wallet_overage_disabled`, `wallet_insufficient` | Overage is off, or the prepaid wallet has insufficient balance. |
These billing responses are **live** on the run, composer, assistant, and managed-knowledge surfaces. They are **absent** on plain CRUD and org-settings routes, which return the `{"detail": ""}` `HTTPException` shape instead. For the complete picture of all error-envelope shapes and which surface emits each, see [Errors & status codes](/api-reference/errors); for credit mechanics and the gate, see [Usage gating & limits](/billing/usage-gating).
The two SDKs map these differently. The Python SDK raises `PaymentRequiredError` for `402` (with subclasses `CreditExhaustedError`, `WalletError`, `QuotaExceededError`), `PermissionError`-style for `403`, and `RateLimitError` for `429`. The JavaScript SDK has no payment error class — `402` falls through to the base `ModulexError`; `429` maps to its rate-limit error. See [SDK errors & retries](/sdks/errors-retries).
```bash cURL
# A 429 includes a Retry-After header; back off and retry.
curl -i -X POST "$MODULEX_BASE_URL/workflows/run" \
-H "Authorization: Bearer $MODULEX_API_KEY" \
-H "X-Organization-ID: $MODULEX_ORG_ID" \
-H "Content-Type: application/json" \
-d '{"workflow_id":"550e8400-e29b-41d4-a716-446655440000","input":{"query":"AI trends"}}'
# HTTP/1.1 402 Payment Required
# {"code":"credit_plan_exhausted","layer":"credit",...}
```
```python Python
from modulex import (
PaymentRequiredError,
QuotaExceededError,
RateLimitError,
)
try:
run = await client.executions.run(
workflow_id="550e8400-e29b-41d4-a716-446655440000",
input={"query": "AI trends"},
)
except RateLimitError as exc: # 429
print("rate limited; back off", exc)
except QuotaExceededError as exc: # 403
print("quota exceeded", exc)
except PaymentRequiredError as exc: # 402 (credit/wallet)
print("out of credits", exc)
```
```javascript JavaScript
import { ModulexError, RateLimitError } from 'modulex-js';
try {
const run = await client.executions.run({
workflowId: '550e8400-e29b-41d4-a716-446655440000',
input: { query: 'AI trends' },
});
} catch (err) {
if (err instanceof RateLimitError) {
console.log('rate limited; back off', err); // 429
} else if (err instanceof ModulexError && err.status === 402) {
console.log('out of credits', err); // 402 — no dedicated payment class
} else {
throw err;
}
}
```
## Step 5 (optional) — Resume an interrupt and read history
If your workflow contains an [interrupt node](/workflow-builder/nodes/interrupt), the stream emits an `interrupt` event and waits. Inspect the checkpoint with `GET /workflows/state/{thread_id}`, then resume with `POST /workflows/resume/{thread_id}`, passing `resume_value`, the same `run_id`, and a schema source (`workflow_id` or inline `workflow`). Resume reuses the **same** `run_id`, so the run is charged only once — re-open the stream on the same `run_id` to keep watching.
```bash cURL — resume
curl -X POST "$MODULEX_BASE_URL/workflows/resume/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer $MODULEX_API_KEY" \
-H "X-Organization-ID: $MODULEX_ORG_ID" \
-H "Content-Type: application/json" \
-d '{
"workflow_id": "550e8400-e29b-41d4-a716-446655440000",
"run_id": "6a7b8c9d-1e2f-3g4h-5i6j-7k8l9m0n1o2p",
"resume_value": { "approved": true }
}'
```
After a run finishes, fetch durable history with `GET /workflow-runs` (list) and `GET /workflow-runs/{run_pk}` (detail, including `input_snapshot` and `output_summary`).
The detail route's path parameter `run_pk` is the run-history table primary key, **not** the execution `run_id` you streamed. They are different identifiers — see [Workflows & runs](/concepts/workflows-and-runs).
```bash cURL — history
curl "$MODULEX_BASE_URL/workflow-runs?workflow_id=550e8400-e29b-41d4-a716-446655440000&limit=20" \
-H "Authorization: Bearer $MODULEX_API_KEY" \
-H "X-Organization-ID: $MODULEX_ORG_ID"
```
```python Python
runs = await client.executions.list_runs(
workflow_id="550e8400-e29b-41d4-a716-446655440000",
limit=20,
)
for row in runs["runs"]:
print(row["run_id"], row["status"]) # e.g. "succeeded"
```
```javascript JavaScript
const runs = await client.workflowRuns.list({
workflowId: '550e8400-e29b-41d4-a716-446655440000',
limit: 20,
});
for (const row of runs.runs) {
console.log(row.run_id, row.status); // e.g. "succeeded"
}
```
Run history is grouped differently across the SDKs: the JavaScript SDK exposes it as `client.workflowRuns`, while the Python SDK folds it into `client.executions` (`list_runs` / `iter_runs` / `get_run`). Both call the same `GET /workflow-runs` routes. See the [SDK parity matrix](/sdks/parity).
## Next steps
The full event taxonomy, frame format, heartbeats, and reconnect semantics.
Base URLs, the request lifecycle, and how every operation is shown three ways.
Pause and resume runs that ask a human for input or approval.
All three error-envelope shapes and which surface emits each.
---
# Schedule a workflow
URL: https://docs.modulex.dev/guides/schedule-a-workflow
Run a deployed ModuleX workflow automatically on a cron schedule: deploy, create the schedule, write a cron expression, and monitor scheduled runs — with cURL, Python, and JavaScript and full parameter and error coverage.
This guide walks you through running a workflow on a cron schedule, end to end: deploy the workflow, create a schedule, write a correct cron expression, then watch the scheduled runs and retry any that fail. Every step is shown via cURL, Python, and JavaScript.
If you want the full parameter, response, and error catalog for every schedule endpoint instead of a walkthrough, go straight to the reference, [Schedules](/workflow-builder/execution/schedule). This page focuses on the common task: a workflow that fires on a calendar cadence.
A schedule fires a workflow's live deployment, never its draft.
Attach a cron cadence to the deployed workflow.
The 5-field cron format, timezones, and common patterns.
Inspect run history and stats, and retry failed runs.
## What you will build
A schedule that runs a deployed workflow automatically at a fixed calendar time — for example, a report workflow every weekday at 09:00 in your timezone. ModuleX fires the workflow's live deployment in the background on that cadence and records each firing as a scheduled run you can inspect.
This guide uses a `cron` schedule. ModuleX also supports a fixed-`interval` cadence (every N seconds); the reference covers both in [Cron and interval cadence](/workflow-builder/execution/schedule#cron-and-interval-cadence).
## Before you start
**Every** schedule endpoint requires the `owner` or `admin` role in the organization — including the read-only ones that list schedules and runs. A plain member receives a `403`, even though they may be able to view the underlying workflow. See [Roles & permissions](/security/roles-permissions) and [Organizations, roles & membership](/concepts/organizations-roles).
A schedule references a workflow's **live deployment**, not its draft. If the workflow has no live deployment when you create the schedule, the call fails with a `400` (not a `404`). [Step 1](#step-1-deploy-the-workflow) covers deploying.
Programmatic calls authenticate with `Authorization: Bearer mx_live_…` plus `X-Organization-ID`. Create a key from the app, or see [Authentication](/api-reference/authentication) and the [Quickstart](/get-started/quickstart).
Schedules are gated to **owner/admin on every route, reads included**, which is broader than most read endpoints in the API. If a teammate gets a `403` listing or reading schedules, check their organization role first. _(Doc-blocking finding §2.9 — schedules require owner/admin; the `member` role is retired.)_
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4470 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** End-to-end walkthrough of scheduling a deployed workflow on a weekday-morning cron and watching the first scheduled run land in history.
**[APP_VIDEO_DETAILS]:** Record in the live app as an owner/admin. Sequence: open a workflow that has a live deployment, open the schedules panel, create a cron schedule with expression `0 9 * * 1-5` and timezone `America/New_York`, show the computed next run time, then cut to the schedule's run history showing a `succeeded` run with its duration. Highlight the cadence field, the timezone field, and the next-run value. Light theme, 16:9, ModuleX docs chrome. Redact any real organization, workflow, or schedule ID.
### Set your variables
The cURL examples below reuse these placeholders. Replace them with your own values; the workflow and organization IDs are UUIDs.
```bash
export MODULEX_API_KEY="mx_live_xxx"
export MODULEX_ORG_ID="0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9"
export WORKFLOW_ID="2b9e7c10-aaaa-bbbb-cccc-1234567890ab"
```
The Python and JavaScript examples create a client once and reuse it. The Python SDK is async, so every call is awaited; it also reads `MODULEX_API_KEY` and `MODULEX_ORGANIZATION_ID` from the environment if you omit the arguments. The JavaScript SDK has no environment-variable fallback — pass the values explicitly.
```python Python
import asyncio
from modulex import Modulex
client = Modulex(
api_key="mx_live_xxx",
organization_id="0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9",
)
WORKFLOW_ID = "2b9e7c10-aaaa-bbbb-cccc-1234567890ab"
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_xxx",
organizationId: "0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9",
});
const WORKFLOW_ID = "2b9e7c10-aaaa-bbbb-cccc-1234567890ab";
```
## Step 1: deploy the workflow
A schedule runs the workflow's **live deployment**. Before scheduling, make sure the workflow is deployed — from the builder, or via the API. Skipping this is the most common reason a `POST /schedules` returns `400` with a message about a missing live deployment.
For how deployments work and how to create one, see [Deploy & versions](/workflow-builder/execution/deploy). Once the workflow has a live deployment, continue.
You can confirm a deployment exists by running the workflow once on demand through [Run via API](/workflow-builder/execution/api-endpoint) before you schedule it. A workflow that runs manually has the live deployment a schedule needs.
## Step 2: create the schedule
Create the schedule with `POST /schedules`. The example below fires the workflow at 09:00 every weekday in `America/New_York` and pins a per-run `input` of `{"mode": "full"}`.
```bash cURL
curl -X POST https://api.modulex.dev/schedules \
-H "Authorization: Bearer $MODULEX_API_KEY" \
-H "X-Organization-ID: $MODULEX_ORG_ID" \
-H "Content-Type: application/json" \
-d '{
"workflow_id": "'"$WORKFLOW_ID"'",
"name": "Nightly report",
"schedule_type": "cron",
"cron_expression": "0 9 * * 1-5",
"timezone": "America/New_York",
"input": { "mode": "full" }
}'
```
```python Python
async def create_schedule():
schedule = await client.schedules.create(
workflow_id=WORKFLOW_ID,
name="Nightly report",
schedule_type="cron",
cron_expression="0 9 * * 1-5",
timezone="America/New_York",
input={"mode": "full"},
)
print(schedule.id, schedule.next_run_at)
return schedule
asyncio.run(create_schedule())
```
```javascript JavaScript
const schedule = await client.schedules.create({
workflowId: WORKFLOW_ID,
name: "Nightly report",
scheduleType: "cron",
cronExpression: "0 9 * * 1-5",
timezone: "America/New_York",
input: { mode: "full" },
});
console.log(schedule.id, schedule.next_run_at);
```
The SDKs accept **camelCase** arguments (`workflowId`, `scheduleType`, `cronExpression`) and send them as snake_case on the wire. Responses always come back **snake_case** (`workflow_id`, `next_run_at`). Creating a schedule returns immediately with `200 OK` (not `201`); the workflow itself runs later, on cadence.
### Create request fields
These are the fields you send to `POST /schedules`. For a cron schedule, supply `cron_expression` and leave `interval_seconds` unset.
The workflow to run. It must have a live deployment, or the call returns `400`.
A human-readable name. Length 1–255 characters.
`cron` for a calendar cadence, or `interval` for a fixed number of seconds. This guide uses `cron`.
Required when `schedule_type` is `cron`. A standard 5-field cron string (see [Cron syntax](#cron-syntax)). Max 100 characters. Validated server-side; an unparseable expression returns `400`.
Required only when `schedule_type` is `interval`. Minimum **60**. Leave unset for cron schedules.
An IANA timezone name (for example `America/New_York`). Max 50 characters. The cron expression is evaluated in this timezone. An unknown name returns `400`.
Optional free-text description.
Per-run state input. On every firing it is merged over the deployment's default input — schedule input wins on conflicting keys. Plain values only; `{{node_id.field}}` references do not resolve at trigger time because there is no upstream node.
Per-run execution config such as `timeout` (the per-run timeout, default one hour) and `recursion_limit`. Merged over the deployment's config on every firing.
Supply exactly one cadence field for the type you chose: `cron_expression` for `cron`, `interval_seconds` for `interval`. A mismatch — for example `schedule_type: "cron"` with no `cron_expression` — returns `400`.
### What you get back
The response is a `ScheduleResponse`. The key field to note now is `next_run_at`: ModuleX computes the first firing from the current time and marks the schedule active (`is_active: true`).
The schedule's ID. Use it for every follow-up call.
Whether the schedule is firing. `false` while paused.
When the schedule will next fire, always stored in UTC.
When it last fired. `null` until the first firing.
Status of the most recent run.
Lifetime count of runs produced. `0` at creation.
Lifetime count of succeeded runs.
Lifetime count of failed runs.
The response also echoes the fields you sent (`workflow_id`, `name`, `schedule_type`, `cron_expression`, `timezone`, `input`, `config`) plus `organization_id`, `created_at`, and `updated_at`. For the full field list, see the [reference response section](/workflow-builder/execution/schedule#response).
```json
{
"id": "8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f",
"workflow_id": "2b9e7c10-aaaa-bbbb-cccc-1234567890ab",
"organization_id": "0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9",
"name": "Nightly report",
"description": null,
"schedule_type": "cron",
"interval_seconds": null,
"cron_expression": "0 9 * * 1-5",
"timezone": "America/New_York",
"input": { "mode": "full" },
"config": {},
"is_active": true,
"next_run_at": "2026-06-22T13:00:00Z",
"last_run_at": null,
"last_run_status": null,
"total_runs": 0,
"successful_runs": 0,
"failed_runs": 0,
"created_at": "2026-06-21T18:30:00Z",
"updated_at": "2026-06-21T18:30:00Z"
}
```
In the example above the schedule is created on a Sunday, so the first weekday firing at 09:00 `America/New_York` lands the following morning. 09:00 Eastern is stored as `13:00Z` because `next_run_at` is always UTC.
### Create errors
| Status | Cause |
| --- | --- |
| `400` | Workflow not found, no live deployment, invalid cron, invalid timezone, `interval_seconds < 60`, or a type/cadence mismatch. Shape: `{"detail": ""}`. |
| `400` | `X-Organization-ID` header missing. |
| `401` | Missing or invalid token. |
| `403` | Caller is not owner/admin, the user is inactive, or the API key's org scope does not match `X-Organization-ID`. |
| `422` | Request-body validation, for example `schedule_type` outside `cron`/`interval` or a name length out of range. Shape: `{"detail": [{"loc": [...], "msg": "...", "type": "..."}]}`. |
| `429` | Rate limit exhausted. The `detail` is an object: `{code, layer, key, current, limit, reason}`. |
| `500` | Unexpected server error: `{"detail": "An unexpected internal server error occurred."}`. |
Schedule routes use FastAPI's `HTTPException` envelope and are **not** behind the credits billing gate, so they never return the flat `DenialEnvelope`. Credits are consumed only when a scheduled run actually executes the workflow (see [Cost of a schedule](#cost-of-a-schedule)). For the full error model, see [Errors & status codes](/api-reference/errors).
## Cron syntax
A `cron_expression` is a **standard 5-field cron string**, evaluated in the schedule's `timezone`:
```text
┌───────────── minute (0–59)
│ ┌───────────── hour (0–23)
│ │ ┌───────────── day-of-month (1–31)
│ │ │ ┌───────────── month (1–12)
│ │ │ │ ┌───────────── day-of-week (0–6, Sunday = 0)
│ │ │ │ │
* * * * *
```
Each field accepts a value, a list (`1,15`), a range (`1-5`), a step (`*/15`), or `*` for "every". ModuleX parses and validates the expression server-side; anything it cannot parse returns a `400`. Maximum length is 100 characters.
### Common patterns
| Expression | Meaning |
| --- | --- |
| `0 9 * * 1-5` | 09:00 every weekday (Monday–Friday) |
| `0 * * * *` | At the top of every hour |
| `*/15 * * * *` | Every 15 minutes |
| `0 0 1 * *` | 00:00 on the 1st of each month |
| `30 2 * * 0` | 02:30 every Sunday |
| `0 9,17 * * 1-5` | 09:00 and 17:00 on weekdays |
### Timezones and `next_run_at`
The cron expression is evaluated in the schedule's `timezone` (default `UTC`). ModuleX computes the next occurrence in that local timezone and then stores it in `next_run_at` as **UTC**. So a schedule with `0 9 * * 1-5` and `America/New_York` shows `13:00Z` (or `14:00Z` during standard time) — that is the same 09:00 local moment, expressed in UTC.
When you change the cadence or timezone with an update, `next_run_at` is recalculated. The base for the next firing is the last run if there is one, otherwise the current time. For the exact recurrence model, see [How `next_run_at` is computed](/workflow-builder/execution/schedule#how-next_run_at-is-computed).
A background **scheduler tick** drives firing, and it runs roughly **every 30 to 60 seconds** depending on deployment. A schedule fires at or shortly after `next_run_at`, never before. Treat sub-minute cron fields and intervals near the 60-second minimum as best-effort — the effective floor on how often a workflow can fire is the tick, not the value you set.
### Edit the cadence later
To change the cron expression, timezone, name, input, or config after creation, send `PUT /schedules/{schedule_id}` with only the fields you want to change. Changing the cadence or timezone recalculates `next_run_at`.
```bash cURL
curl -X PUT https://api.modulex.dev/schedules/8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f \
-H "Authorization: Bearer $MODULEX_API_KEY" \
-H "X-Organization-ID: $MODULEX_ORG_ID" \
-H "Content-Type: application/json" \
-d '{ "cron_expression": "0 8 * * 1-5" }'
```
```python Python
updated = await client.schedules.update(
"8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f",
cron_expression="0 8 * * 1-5",
)
```
```javascript JavaScript
const updated = await client.schedules.update(
"8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f",
{ cronExpression: "0 8 * * 1-5" },
);
```
A `null` field in an update is **dropped**, not applied, so you cannot clear `description`, `input`, or `config` back to empty through update. `is_active` is not updatable here — use [pause and resume](#pause-or-resume-a-schedule) instead. If every field resolves to `null`, the call returns `400` with `{"detail": "No updates provided"}`. Full update rules are in the [reference](/workflow-builder/execution/schedule#update-a-schedule).
## Step 3: monitor scheduled runs
Every firing produces a **scheduled run** record. Use the run endpoints to confirm your schedule is working and to act on failures.
### List the schedule's runs
`GET /schedules/{schedule_id}/runs` lists runs newest-first by scheduled time. Filter by `status` while debugging, and page with `limit` (1–100, default 50) and `offset`.
```bash cURL
curl "https://api.modulex.dev/schedules/8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f/runs?limit=20" \
-H "Authorization: Bearer $MODULEX_API_KEY" \
-H "X-Organization-ID: $MODULEX_ORG_ID"
```
```python Python
runs = await client.schedules.list_runs(
"8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f", limit=20,
)
for r in runs.runs:
print(r.scheduled_at, r.status, r.duration_seconds)
```
```javascript JavaScript
const { runs } = await client.schedules.runs(
"8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f",
{ limit: 20 },
);
for (const r of runs) {
console.log(r.scheduled_at, r.status, r.duration_seconds);
}
```
Each item is a `ScheduleRunResponse`. The fields most useful for monitoring:
The scheduled-run record ID. This is the `run_id` argument you pass to the get-run and retry endpoints.
When the run was supposed to fire.
When execution began.
When execution finished.
`completed_at − started_at`, in seconds.
The run status (see the table below).
The failure reason, when the run failed.
What triggered the run: `scheduler` for a normal firing, or `retry` for a manual retry.
The workflow execution's run ID, prefixed `sched_`. Populated once execution starts. This is distinct from the record `id` above.
The execution thread ID, prefixed `sched_thread_`.
A scheduled run carries **three different IDs** — the record `id`, the execution `run_id` (`sched_…`), and the `thread_id` (`sched_thread_…`). When you call get-run or retry, the `run_id` argument is the record's `id`, **not** the execution `run_id`. Keep them straight; see [Workflows & runs](/concepts/workflows-and-runs) for the full run-identity model. _(Doc-blocking finding §2.9 — three distinct run-id identities.)_
#### Run status values
| Status | Meaning |
| --- | --- |
| `pending` | The run record exists; execution has not started. |
| `running` | Execution is in progress. |
| `succeeded` | The workflow completed successfully. |
| `failed` | Execution raised an error; see `error_message`. |
| `cancelled` | The run was cancelled. |
| `skipped` | The firing was skipped — for example the workflow lost its live deployment between scheduling and execution. |
### Check the success rate
`GET /schedules/{schedule_id}/runs/stats` rolls up recent runs over a `days` window (1–90, default 7). Use it to spot a schedule that is silently failing.
```bash cURL
curl "https://api.modulex.dev/schedules/8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f/runs/stats?days=30" \
-H "Authorization: Bearer $MODULEX_API_KEY" \
-H "X-Organization-ID: $MODULEX_ORG_ID"
```
```python Python
stats = await client.schedules.run_stats(
"8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f", days=30,
)
print(stats.success_rate, stats.avg_duration_seconds)
```
```javascript JavaScript
const stats = await client.schedules.runStats(
"8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f",
{ days: 30 },
);
console.log(stats.success_rate, stats.avg_duration_seconds);
```
```json
{
"period_days": 30,
"total_runs": 168,
"successful_runs": 160,
"failed_runs": 8,
"success_rate": 95.24,
"avg_duration_seconds": 38.7,
"min_duration_seconds": 12.1,
"max_duration_seconds": 91.4
}
```
The scale of `success_rate` is reported inconsistently across our sources: the API computes it as a **percentage** (for example `95.24`), while the JavaScript SDK types describe it as a **fraction** (0.0–1.0). Read it defensively — branch on whether the value exceeds `1` — until this is reconciled.
### Retry a failed run
If a firing failed or was cancelled, retry it with `POST /schedules/{schedule_id}/runs/{run_id}/retry`, where `run_id` is the scheduled-run record's `id`. The retry queues a brand-new background execution with `triggered_by` set to `retry`; it does not run inline and does not modify the original run.
```bash cURL
# 1. Find the failed runs
curl "https://api.modulex.dev/schedules/8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f/runs?status=failed" \
-H "Authorization: Bearer $MODULEX_API_KEY" \
-H "X-Organization-ID: $MODULEX_ORG_ID"
# 2. Retry one by its record id
curl -X POST https://api.modulex.dev/schedules/8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f/runs/11111111-2222-3333-4444-555555555555/retry \
-H "Authorization: Bearer $MODULEX_API_KEY" \
-H "X-Organization-ID: $MODULEX_ORG_ID"
```
```python Python
failed = await client.schedules.list_runs(
"8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f", status="failed",
)
for r in failed.runs:
result = await client.schedules.retry_run(
"8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f", r.id,
)
print("retried", result.original_run_id)
```
```javascript JavaScript
const { runs: failed } = await client.schedules.runs(
"8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f",
{ status: "failed" },
);
for (const r of failed) {
const result = await client.schedules.retryRun(
"8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f",
r.id,
);
console.log("retried", result.original_run_id);
}
```
On success the response is `{ "message": "Retry scheduled", "original_run_id": "" }`. Retrying a run whose status is anything other than `failed` or `cancelled` returns `400` with `{"detail": "Can only retry failed or cancelled runs. Current status: "}`.
There is no public "run now" endpoint for a single schedule. To trigger an ad-hoc execution, either retry a finished run, or run the workflow directly through [Run via API](/workflow-builder/execution/api-endpoint). For the get-one-run endpoint and the full run schema, see the [reference run section](/workflow-builder/execution/schedule#run-history-and-statistics).
## Pause or resume a schedule
To stop a schedule firing without deleting its history, pause it; bring it back with resume. While paused (`is_active: false`), the scheduler tick skips it.
```bash cURL
# Pause
curl -X POST https://api.modulex.dev/schedules/8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f/pause \
-H "Authorization: Bearer $MODULEX_API_KEY" \
-H "X-Organization-ID: $MODULEX_ORG_ID"
# Resume
curl -X POST https://api.modulex.dev/schedules/8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f/resume \
-H "Authorization: Bearer $MODULEX_API_KEY" \
-H "X-Organization-ID: $MODULEX_ORG_ID"
```
```python Python
await client.schedules.pause("8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f")
await client.schedules.resume("8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f")
```
```javascript JavaScript
await client.schedules.pause("8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f");
await client.schedules.resume("8f1c2a40-1d3e-4b9a-9c77-1a2b3c4d5e6f");
```
Resume **restarts the clock**: it recomputes `next_run_at` from now rather than resuming from where the schedule left off. A paused daily schedule resumed at 14:00 computes its next firing from 14:00. If you need the original cadence to hold exactly, leave the schedule active and rely on its computed `next_run_at` instead of pausing. Deleting a schedule (`DELETE /schedules/{schedule_id}`) removes it **and all of its run history** and cannot be undone — pause instead when you want to keep history.
## Cost of a schedule
The schedule API itself — create, read, update, pause, resume, run history — does **not** consume credits. Credits are consumed when a scheduled firing **executes the workflow**, exactly as for a manual run: any managed-model, managed-knowledge, or other metered work inside the workflow draws down credits at execution time.
A schedule that fires every minute meters the same as running that workflow manually every minute. Size the cadence accordingly, and review [Credits & metering](/billing/credits) and [Usage gating & limits](/billing/usage-gating) before scheduling a high-frequency, credit-heavy workflow.
## Troubleshooting
The workflow has no live deployment yet. Deploy it first (see [Deploy & versions](/workflow-builder/execution/deploy)), then create the schedule. This is a `400`, not a `404`.
Schedule routes require the `owner` or `admin` role on every endpoint, reads included. A plain member cannot list, read, or manage schedules. Check the teammate's organization role — see [Roles & permissions](/security/roles-permissions).
Confirm `is_active` is `true` (a paused schedule is skipped) and that `next_run_at` is in the future and in the expected UTC time. Remember the scheduler tick runs every 30–60 seconds, so firings land at or just after `next_run_at`, never before. Sub-minute cadences are best-effort.
A `skipped` run means the firing was reached but could not execute — most often because the workflow lost its live deployment between scheduling and execution. Re-deploy the workflow.
The expression must be a valid 5-field cron string (max 100 characters) that ModuleX can parse, and the `timezone` must be a valid IANA name. Re-check both against [Cron syntax](#cron-syntax).
## Related pages
The complete endpoint reference: every parameter, response field, and error.
Create the live deployment a schedule needs.
Trigger a workflow on demand instead of on a cadence.
Authenticate, run a workflow, and stream the result.
Why schedules require the owner or admin role.
How scheduled runs consume credits when they execute.
---
# Account & access — help
URL: https://docs.modulex.dev/help/account-access
How to sign in, switch organizations, understand roles, and recover access in ModuleX.
Short answers about signing in, working across organizations, and what each role can do. For the full picture, follow the links in each answer to the canonical page.
What owners and admins can each do.
How `X-Organization-ID` picks which organization you act in.
## Common questions
In the app, use the organization switcher to change which organization you are working in. From the API or an SDK, set the `X-Organization-ID` header (the organization's UUID) on each request. See [org context](/security/org-context).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4510 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The organization switcher in the ModuleX app.
**[SCREENSHOT_DETAILS]:** Capture the top-bar / sidebar organization switcher open, showing a list of organizations the user belongs to with the active one marked. Crop tightly to the switcher control and its dropdown. Light theme, desktop width, no personal data visible.
There are two roles: **owner** and **admin**. Owners manage billing and own the organization; admins can invite people, manage credentials, and build and run workflows, the AI Composer, and the Assistant. The `member` role has been retired, so there is no longer a read-only role. See [roles & permissions](/security/roles-permissions).
A few older organizations may still show a leftover `member` value on some records. It is deprecated and not a role you can assign; treat owner and admin as the live roles.
ModuleX uses Clerk as its identity provider, so you sign in through Clerk. There is no separate ModuleX username and password. Your account and a starter organization are created on your first sign-in. See [getting started](/help/getting-started).
No. API keys (they start with `mx_live_`) are shown only once when you create them and are not stored in a way that lets us show them again. Delete the old key and create a new one in Settings, then update wherever the old key was used. See [authentication](/api-reference/authentication).
The organization you are calling is not one you belong to. This usually means `X-Organization-ID` is set to the wrong organization, or your API key is scoped to a different one. Set the header to an organization you are a member of. See [org context](/security/org-context).
Use Clerk's sign-in and recovery options (password reset, single sign-on, and any other method your organization has enabled). If you still cannot get in after that, reach out through [getting help](/help/getting-help).
## Selecting your organization from code
Every organization-scoped request needs an organization. Send your API key in the `Authorization` header and the organization UUID in `X-Organization-ID`. The SDKs take the same two values when you create the client.
```bash cURL
curl https://api.modulex.dev/auth/me \
-H "Authorization: Bearer mx_live_2J9vK4xM..." \
-H "X-Organization-ID: a1b2c3d4-0000-0000-0000-000000000000"
```
```python Python
import asyncio
from modulex import Modulex
async def main():
async with Modulex(
api_key="mx_live_2J9vK4xM...",
organization_id="a1b2c3d4-0000-0000-0000-000000000000",
) as client:
me = await client.auth.me()
print(me)
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_2J9vK4xM...",
organizationId: "a1b2c3d4-0000-0000-0000-000000000000",
});
const me = await client.auth.me();
console.log(me);
```
If you leave `X-Organization-ID` off an organization-scoped request, the API returns `400` with `X-Organization-ID header is required`. If it points at an organization you are not in, you get `403` with `User is not a member of organization`. See [org context](/security/org-context).
## Keep reading
How organizations, membership, and roles fit together.
Signing up and making your first call.
---
# API & SDKs — help
URL: https://docs.modulex.dev/help/api-sdks
Use ModuleX from your own code: the JavaScript and Python SDKs, how to authenticate, the base URL, streaming run output, and rate limits.
Everything you can do in the ModuleX app, you can also do from code. The REST API, the JavaScript SDK, and the Python SDK all talk to the same backend, so a workflow you build in the app runs the same way when you call it from a script.
This page answers the questions people ask most when they start using ModuleX from code. For the full developer reference, see the [API overview](/api-reference/overview) and the [SDKs overview](/sdks/overview).
## Quick answers
JavaScript and Python, both with streaming. A few features differ between them.
Send your `mx_live_` API key as a Bearer token plus your organization ID.
Every request goes to `https://api.modulex.dev` by default.
Follow a run event by event with `listen()` or the listen endpoint.
## Common questions
Yes — ModuleX publishes an official JavaScript SDK (`modulex-js`) and an official Python SDK (`modulex-python`), and both support live streaming. They cover the same operations with a handful of differences. The biggest one to know: managing **subscriptions** (plans, billing, checkout, the customer portal) is available in the **Python SDK only** — the JavaScript SDK has no subscriptions methods. For the full side-by-side comparison, see the [SDK parity matrix](/sdks/parity); to get started, see the [SDKs overview](/sdks/overview).
Send two things on every request: your API key as `Authorization: Bearer mx_live_…`, and your organization in the `X-Organization-ID` header. In the SDKs you pass your API key and organization ID when you create the client, and it adds both headers for you. Create and copy your key from Settings, API Keys (it is shown only once). Full details are on the [authentication](/api-reference/authentication) page.
`https://api.modulex.dev`, with no version segment in the path — do not add `/v1` or `/api`. The SDKs use this base URL by default, so you normally do not set it yourself. See [base URLs & versioning](/api-reference/environments) for the details.
Instead of waiting for a run to finish, you can follow it event by event. In the SDKs, call `listen()` and read the events as they arrive; over plain HTTP, open the run's listen endpoint, which streams server-sent events. This is how the app shows live progress. See [SSE run streaming](/realtime/sse-streaming) and [streaming & HITL](/sdks/streaming-hitl).
Yes — a per-minute limit applies to your API key (and a higher combined limit across all your keys). If you go over it, ModuleX returns a `429` response with a `Retry-After` header telling you how many seconds to wait before retrying. The SDKs read that header and back off automatically. See [rate limiting](/api-reference/rate-limiting).
In the Python SDK, yes: if you do not pass them in code, it reads `MODULEX_API_KEY`, `MODULEX_ORGANIZATION_ID`, and `MODULEX_BASE_URL` from the environment. The JavaScript SDK does **not** read environment variables on its own — you must pass your API key (and organization ID) to the client explicitly. See the [JavaScript SDK](/sdks/javascript) and [Python SDK](/sdks/python) pages.
## Authenticate and make a call
Every operation looks the same in all three: send your `mx_live_` key as a Bearer token plus your `X-Organization-ID`. Here is listing your workflows.
```bash cURL
curl https://api.modulex.dev/workflows \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: your-org-id"
```
```python Python
from modulex import Modulex
async with Modulex(
api_key="mx_live_your_api_key",
organization_id="your-org-id",
) as client:
page = await client.workflows.list()
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_your_api_key",
organizationId: "your-org-id",
});
const { workflows } = await client.workflows.list();
```
The Python SDK is async — call its methods with `await` inside an `async` function. The JavaScript SDK uses promises, so `await` its methods too.
## Stream a run live
To watch a run as it happens, call `listen()` with the run's id and read events until the run finishes.
```bash cURL
curl -N https://api.modulex.dev/workflows/listen/your-run-id \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: your-org-id" \
-H "Accept: text/event-stream"
```
```python Python
async for event in client.executions.listen("your-run-id"):
print(event.event, event.data)
```
```javascript JavaScript
for await (const event of client.executions.listen("your-run-id")) {
console.log(event.type, event.data);
}
```
## Handle rate limits
When you exceed the per-minute limit, ModuleX returns `429` with a `Retry-After` header (seconds to wait). The SDKs honor it and retry for you; if you call the API directly, wait that long before retrying.
A `429` means too many requests in the current window — not an error in your request itself.
The `Retry-After` response header tells you how many seconds to wait before trying again.
Pause for that many seconds and send the request again. The SDKs do this automatically.
For what other status codes mean (`401`, `402`, `403`, and more), see [errors & troubleshooting](/help/errors-troubleshooting) and the full [errors reference](/api-reference/errors).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4580 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** the API Keys screen where a user creates a `mx_live_` key
**[SCREENSHOT_DETAILS]:** Capture Settings, API Keys in the live ModuleX app showing the create-key dialog with the one-time key reveal. Light mode, 16:9, redact any real key value. Highlight the "copy" action and the note that the key is shown only once.
## Where to go next
The full authentication reference: Bearer keys, organization context, and headers.
Install and configure the JavaScript and Python SDKs.
An end-to-end walkthrough in cURL, Python, and JavaScript.
Exactly which operations each SDK supports, including the Python-only subscriptions.
---
# Billing, plans & credits — help
URL: https://docs.modulex.dev/help/billing-credits
How ModuleX bills: plans, what a credit is, what uses credits, and what happens when you run out. Quick answers for managing cost and usage.
Short answers to the questions people ask most about paying for ModuleX and tracking what they use. For the full detail, follow the link in each answer.
Free, Pro, Max, and Enterprise — what each includes.
What a credit is and exactly what consumes credits.
The prepaid balance that covers usage beyond your plan.
## Billing, plans & credits
There is a Free plan, paid Pro and Max plans, and custom Enterprise pricing. Pro is `$25/month` and includes 5,000 credits per month; Max is `$100/month` and includes 20,000 credits per month. See the full breakdown in [Plans & pricing](/billing/plans).
A credit is how managed usage is measured: `100 credits = $1.00` (one credit is `$0.01`). Running workflows, AI turns, and knowledge searches all draw down credits. See [Credits & metering](/billing/credits).
Each workflow run or AI turn costs a base credit, plus the cost of any managed AI model usage, knowledge searches, and tool calls. If you bring your own model key (BYOK), that usage is billed by the provider and is not charged in ModuleX credits. See [Credits & metering](/billing/credits).
Managed runs are blocked with a `402` "payment required" response until you have budget again. Top up your [wallet](/billing/wallet), turn on overage, or upgrade your plan in [Plans & pricing](/billing/plans).
Your plan gives a monthly credit allowance. The wallet is a separate prepaid balance that covers usage after the allowance runs out — this is called overage, and you can turn it on for paid plans. See [Wallet & top-ups](/billing/wallet).
Open your dashboard to see credit spend and remaining balance, with per-run detail in your logs. For what each line item means, see [Credits & metering](/billing/credits).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4520 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** the usage/analytics view showing credit spend and remaining balance
**[SCREENSHOT_DETAILS]:** capture the dashboard analytics page in the ModuleX app for an org with some recorded usage; show the credits-spent and credits-remaining figures and the spend-over-time chart; light mode; 16:9; no real customer data
Contact support to request a refund. Refunds are usually returned as wallet credit rather than to your card. See [Wallet & top-ups](/billing/wallet).
Pro and Max can be billed annually. The marketed annual price and the amount charged at checkout do not currently agree, so confirm the exact annual amount on the Stripe checkout screen before you pay. Pricing details are on [Plans & pricing](/billing/plans).
BYOK (bring your own key) usage is never charged in ModuleX credits — it is tracked for analytics only and billed directly by the upstream provider.
## Keep reading
What a `402`, `403`, or `429` means and how to clear it.
The admission gate and the responses it returns when limits are hit.
---
# AI Composer & Assistant — help
URL: https://docs.modulex.dev/help/composer-assistant
Quick answers about ModuleX's two AI helpers: the AI Composer that builds workflows from plain English, and the Assistant that uses your connected tools step by step — including who can run them and what to do when one pauses.
ModuleX has two AI helpers, and they do different jobs. The **AI Composer** turns a plain-English description into an editable workflow. The **Assistant** is a chat that uses your connected tools step by step to get something done, without building a workflow. This page answers the questions people ask most about both. Each answer links to a fuller guide.
The text-to-workflow agent that drafts an editable workflow from a prompt.
The agentic chat that uses your tools to finish a task — no workflow needed.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4540 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** The AI Composer generating a workflow from a plain-English prompt.
**[APP_VIDEO_DETAILS]:** Screen recording in the workflow builder. Show a user typing a prompt into the Composer panel (for example, "Search GitHub and summarize the top result"), then the Composer streaming its work — adding nodes onto the canvas one at a time — and finishing with an editable workflow the user can save. Highlight the Composer chat panel on the left and the canvas updating live on the right. 30 to 45 seconds, 16:9, light mode, annotate the prompt box and the "save changes" step.
## Common questions
The **AI Composer** turns a plain-English description into a complete, editable workflow that you save and run later. The **Assistant** is a chat that uses your connected tools step by step to finish a task right now, and it does not build or change any workflow. In short: use the Composer to *build* something reusable; use the Assistant to *get something done* in the moment. See [AI Composer](/concepts/ai-composer) and the [Assistant overview](/assistant/overview).
Open the Composer in the workflow builder and describe what you want — for example, "Search GitHub and summarize the top result." It builds the workflow on the canvas for you, then you review the changes and **save** them (or **revert** to undo). You can keep chatting to refine it. See [AI Composer in the builder](/workflow-builder/composer) and the [build with Composer guide](/guides/build-with-composer).
Both the Composer and the Assistant require an **owner** or **admin** role in the organization. There is no longer a read-only `member` role, so anyone without owner or admin access cannot run them. Ask an owner or admin to change the teammate's role, or to run the task for them. See [roles & permissions](/security/roles-permissions).
A tool it wants to use needs a credential for that service, so it pauses and asks you to connect the account. Connect it when prompted — for an OAuth service this sends you to the provider to approve access — and the Assistant continues on its own from where it stopped. See [credentials & integrations help](/help/credentials-integrations).
It is almost always **paused waiting for your input**, not failed. The Composer and the Assistant pause to ask a question — a choice, a yes/no, some text, or a request to connect a service. Answer the prompt and the run picks up where it left off. See the [Assistant overview](/assistant/overview).
The Composer and the Assistant each charge **one run credit per turn** (one message you send), plus the cost of any AI model and tool usage. Bringing your own model key (BYOK) is not charged in credits. See [credits & metering](/billing/credits).
## Keep reading
A full walkthrough from a prompt to a running workflow.
Who can use the Composer, the Assistant, and schedules.
---
# Credentials & integrations — help
URL: https://docs.modulex.dev/help/credentials-integrations
Quick answers for connecting external services to ModuleX: add an OAuth or API-key credential, browse the 175 integrations, find a tool, bring your own keys (BYOK), how credentials are encrypted, fix a broken OAuth connection, and build your own integration.
Short answers to the questions people ask most about connecting ModuleX to the services you already use, so your workflows and the Assistant can act on your behalf. For the full detail, follow the link in each answer.
Connect ModuleX to 175 services and call their tools from workflows and the Assistant.
How integrations authenticate: OAuth2, API keys, bearer tokens, and managed keys.
Browse the full catalog of 175 integrations by category.
Create, set a default, test, and remove credentials in the app or via the API.
## Credentials & integrations
Add a credential for the service you want to use. For an OAuth integration you click connect and approve access on the provider's site (for example GitHub); for a key-based integration you paste an API key or token. Adding and managing credentials needs an owner or admin role on the organization. See [Authentication & credentials](/integrations/authentication) for each connection type.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4560 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** connecting an OAuth integration (GitHub) from the credentials screen in the ModuleX app
**[SCREENSHOT_DETAILS]:** capture the credentials area in the ModuleX app while connecting GitHub; show the connect/authorize action that hands off to the provider's OAuth consent screen, and the connected credential appearing in the list afterward; light mode; 16:9; no real customer data or tokens visible
There are 175 integrations available today, spanning developer tools, communication, CRM, data, and more. Browse them all in the [integration catalog](/integrations/catalog), or read the [integrations overview](/integrations/overview) for what they can do.
A tool usually only becomes available once you have connected its integration. Add a credential for that service and its actions appear for use in workflows and the Assistant. See [Managing credentials](/integrations/managing-credentials).
Yes. With bring-your-own-key (BYOK) you supply your own credential for a provider, and that usage is billed by the provider directly — it is not charged in ModuleX credits. ModuleX-managed keys are the alternative and are metered in credits. See [Authentication & credentials](/integrations/authentication) and [Credits & metering](/billing/credits).
Credentials are encrypted at rest with a key scoped to your organization and the specific credential, so they cannot be reused outside it. Secrets are decrypted only when a tool runs, and the API returns masked values (for example `start***end`) rather than the raw secret. See [Data security & encryption](/security/data-encryption) and [Credentials & OAuth2](/concepts/credentials-oauth).
For most providers, OAuth tokens refresh automatically just before they expire, so you do not need to do anything. If a connection breaks, reconnect the credential — remove it and connect the service again. The manual "refresh" action in the app is a [known limitation](/help/known-limitations) and may not work, so prefer reconnecting. See [Managing credentials](/integrations/managing-credentials).
Yes, but not from inside the app yet. You add a custom integration by packaging it as code (a tool package the runtime discovers) or by connecting a [custom MCP server](/integrations/building/custom-mcp). See [Build an integration](/integrations/building/overview) to get started.
Connecting, testing, and removing credentials all require an owner or admin role on the organization. If a teammate cannot add or see a credential, check their role under [Account & access](/help/account-access).
## Related help
Connect a provider key for BYOK embeddings or an external vector store.
The OAuth refresh button and other things to be aware of.
What a `401`, `402`, or `403` means and how to clear it.
---
# Errors & troubleshooting — help
URL: https://docs.modulex.dev/help/errors-troubleshooting
What the common ModuleX error codes mean — 401, 402, 403, 404, 429, and 500 — and how to fix them, plus how to debug a failed node or tool.
Most errors fall into a handful of codes, and each one has a clear fix. This page explains what the common codes mean in plain terms and what to do about them. For the full technical reference, follow the link in each answer.
The complete reference: every status code and the response shapes behind it.
The admission gate and the `402` / `403` / `429` responses it returns.
## Errors & troubleshooting
Here is the short version:
- `401` — you are not signed in, or your API key or token is invalid.
- `402` — your organization is out of credits (payment required).
- `403` — you do not have permission, or you are calling the wrong organization.
- `404` — the thing you asked for does not exist, or it is not in your organization.
- `429` — too many requests, or a usage limit was hit.
- `500` — something went wrong on our side.
For the precise meaning and response body of each code, see [errors & status codes](/api-reference/errors).
Your API key or token is missing or invalid. API keys start with `mx_live_` and go in the `Authorization: Bearer` header, alongside the `X-Organization-ID` header. Check the value is correct and not expired — see [authentication](/api-reference/authentication).
Either you do not have the right role for that action, or your key is scoped to a different organization than the one you are calling. Building or running with Composer, the Assistant, and schedules needs an owner or admin role; see [roles & permissions](/security/roles-permissions). A `403` on a run, Composer, Assistant, or managed-knowledge request can also mean a plan limit was reached — see [usage gating & limits](/billing/usage-gating).
Your organization is out of credits, so the request was blocked with a "payment required" response. Top up your [wallet](/billing/wallet), turn on overage, or upgrade your plan in [plans & pricing](/billing/plans). For what counts as managed usage, see [credits & metering](/billing/credits).
You have hit a rate limit, or a usage limit on a run. Wait for the number of seconds given in the `Retry-After` header on the response, then retry. See [rate limiting](/api-reference/rate-limiting).
Open the run in your run history and look at the failed node's error message. The usual causes are a missing or expired credential, bad input passed into the node, or the external service returning its own error. To reconnect a credential, see [credentials & integrations](/help/credentials-integrations); for retry behavior in a workflow, see [error handling & retries](/workflow-builder/error-handling-retries).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4590 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** the run history view with a failed node expanded to show its error message
**[SCREENSHOT_DETAILS]:** capture the run detail / run history page in the ModuleX app for a run that has one failed node; expand the failed node so its error message and inputs are visible; light mode; 16:9; no real customer data
## A note on 402, 403, and 429
These three codes mean different things depending on where they come from, so it helps to know which is which.
On the **run, Composer, Assistant, and managed-knowledge** surfaces, a `402`, `403`, or `429` from a usage limit returns a flat response that tells you exactly which limit was hit — for example `{code, layer, key, current, limit, reason}`. Plain create/read/update/delete and settings requests instead return the simpler `{detail}` message shape. The full breakdown of these response shapes is in [errors & status codes](/api-reference/errors).
## Debug a failed request from code
When you call ModuleX from the API or an SDK, every request uses `Authorization: Bearer mx_live_…` together with the `X-Organization-ID` header. If a request fails, read the HTTP status code and the response body — the SDKs raise typed errors you can catch so you can branch on the status and the included fields.
```bash cURL
# Add -i to see the status line and headers (such as Retry-After on a 429)
curl -i -X POST https://api.modulex.dev/workflows/run \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: org_your_org_id" \
-H "Content-Type: application/json" \
-d '{ "workflow_id": "wf_29ab83c1", "input": { "topic": "release notes" } }'
```
```python Python
from modulex import Modulex
from modulex import RateLimitError, BillingError, AuthenticationError, ModulexError
client = Modulex(
api_key="mx_live_your_api_key",
organization_id="org_your_org_id",
)
try:
run = await client.executions.run(
workflow_id="wf_29ab83c1",
input={"topic": "release notes"},
)
except AuthenticationError:
print("401 — check your API key and organization id")
except RateLimitError as err:
print(f"429 — retry after {err.retry_after} seconds")
except BillingError as err:
# 402 / 403 / 429 usage limit — err.code and err.layer say which one
print(f"Usage limit hit: {err.code} ({err.layer})")
except ModulexError as err:
print(f"Request failed with status {err.status_code}")
```
```javascript JavaScript
import { Modulex } from "modulex-js";
import { AuthenticationError, RateLimitError, ModulexError } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_your_api_key",
organizationId: "org_your_org_id",
});
try {
const run = await client.executions.run({
workflowId: "wf_29ab83c1",
input: { topic: "release notes" },
});
} catch (err) {
if (err instanceof AuthenticationError) {
console.log("401 — check your API key and organization id");
} else if (err instanceof RateLimitError) {
console.log(`429 — retry after ${err.retryAfter} seconds`);
} else if (err instanceof ModulexError) {
// 402 / 403 usage limits expose .code, .layer, and .reason on the error
console.log(`Request failed (${err.status}): ${err.code ?? "error"}`);
}
}
```
The SDK error classes differ slightly between languages — for example, the Python SDK has a dedicated billing error family that the JavaScript SDK folds into its base error. See [errors & status codes](/api-reference/errors) for the exact mapping.
## Related help
Signing in, organizations, and the roles behind a `403`.
What it costs, what uses credits, and how to clear a `402`.
Reconnect an expired credential behind a failed tool or node.
Behaviors to be aware of so you do not chase a non-bug.
---
# Getting help — Help
URL: https://docs.modulex.dev/help/getting-help
Reach a human at ModuleX: how to contact support, what to include in your message, where to find the community, and how to check whether the platform is up.
When something is not working — or you just want a person to look at it — this page tells you who to contact, what to include so they can help fast, and how to check whether the issue is on ModuleX's side.
Email the team. Include your organization ID, what you were doing, and any error code.
See whether the platform and its health checks are up before you report a problem.
Ask questions and share workflows with other ModuleX users.
Found a gap or want to add an integration? Here is how to help.
## Frequently asked questions
Email **support@modulex.dev**. To get help fast, include three things: your **organization ID**, **what you were doing** when it happened, and **any error code** you saw (for example `402` or `403`). See [what to include](#what-should-i-include-in-a-support-request) below for the full list, and [Errors & troubleshooting](/help/errors-troubleshooting) to decode an error code first.
Your organization ID, a short description of what you were doing, and any error code or message. The more specific you are, the faster the team can reproduce it. See [the checklist](#what-should-i-include-in-a-support-request) below.
It is the value you send in the `X-Organization-ID` header on API calls, and it is shown in the app's organization settings. Learn how the org context works in [Org context & X-Organization-ID](/security/org-context).
ModuleX exposes a public liveness check at `GET /system/health`, documented on the [System status & health](/reference/status) page, so you can confirm the API is up. A hosted status / incident page (with uptime history and live incident updates) is not confirmed yet — see [Is there a hosted status or incident page?](#is-there-a-hosted-status-or-incident-page) below.
Support depends on your plan: Free uses the community, Pro adds Discord, Max adds email plus Discord, and Enterprise includes dedicated support. See [Support by plan](#what-support-do-i-get-on-my-plan) below, and [Plans & pricing](/billing/plans) for the full comparison.
Join the ModuleX Discord at `discord.gg/jEyCABwU9E` to ask questions and share workflows. You can also open issues on GitHub at `github.com/ModuleXAI`. More detail in [Where can I ask the community?](#where-can-i-ask-the-community) below.
File it on GitHub at `github.com/ModuleXAI`, or email **support@modulex.dev** if it involves your account or data. If you want to fix or add something yourself, see [Contributing](/resources/contributing).
A few flows are documented gaps rather than bugs (for example, deleting several nodes at once, or the "refresh OAuth" button). Check [Known limitations](/help/known-limitations) before you file a report — your issue may already be listed with a workaround.
## How do I contact support?
Email **support@modulex.dev**. A clear first message saves a round trip — include the details below.
Support is a paid-plan benefit. Free accounts are pointed to the [community channels](#where-can-i-ask-the-community); paid plans add direct support. See [Support by plan](#what-support-do-i-get-on-my-plan).
### What should I include in a support request?
The ID of the organization you were working in — the same value you send as the `X-Organization-ID` header. It tells the team exactly which account and data to look at. See [Org context & X-Organization-ID](/security/org-context).
A short, concrete description: the action you took, the workflow or chat involved, and what you expected to happen versus what actually happened.
Copy the exact error code (for example `402`, `403`, or `429`) and any message text. If you are not sure what it means, [Errors & troubleshooting](/help/errors-troubleshooting) explains the common ones first.
The approximate date and time, and whether it is still happening or was a one-off. This helps the team line your report up with logs.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4610 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** where to find your organization ID in the app's organization settings.
**[SCREENSHOT_DETAILS]:** capture the organization settings screen with the organization ID field visible and labelled; light mode; redact any real ID with a placeholder such as `org_…`; highlight the ID field with a callout. 16:9.
## Is there a status page?
To check whether the platform itself is up, use the health endpoints documented on the [System status & health](/reference/status) page — `GET /system/health` is a public liveness check that returns the service status without authentication.
### Is there a hosted status or incident page?
A hosted status / incident page (uptime history, live incident posts) is **not confirmed** in the current sources. Until one is published, use the [health endpoints](/reference/status) to verify the API is reachable, then contact [support](#how-do-i-contact-support) if it is up but your action still fails. **TBD** — this page will link to a hosted status page once one exists.
## What support do I get on my plan?
The support channel scales with your plan. Confirm the current details on [Plans & pricing](/billing/plans).
| Plan | Support channel |
| --- | --- |
| Free | Community (Discord, GitHub) |
| Pro | Discord |
| Max | Email + Discord |
| Enterprise | Dedicated support |
Enterprise teams also get hands-on onboarding and a dedicated support contact. See [ModuleX for enterprise](/enterprise/overview) and [Contact sales](/enterprise/contact-sales).
## Where can I ask the community?
For questions, ideas, and sharing workflows, the community is the fastest place to start — and the primary support channel on the Free plan.
Chat with other ModuleX users and the team at `discord.gg/jEyCABwU9E`.
Report bugs, request features, and browse the code at `github.com/ModuleXAI`.
## Before you reach out
A quick self-check often resolves the issue faster than waiting for a reply.
Common codes like `401`, `402`, `403`, and `429` each have a known cause and fix.
Some behaviours are documented gaps with workarounds, not bugs.
Use the health endpoints to rule out a platform-wide issue.
---
# Getting started — help
URL: https://docs.modulex.dev/help/getting-started
Answers for people brand new to ModuleX: how to sign up, create your first API key, try the product, choose between the app and the API, and the free plan.
New to ModuleX? This page answers the first questions most people have — how to sign up, where your API key comes from, the fastest way to try things, and what the free plan includes. Each answer links to a fuller guide if you want the details.
Sign in, create an API key, and make your first authenticated call.
Run a workflow from code and stream the result.
See what the Free, Pro, Max, and Enterprise plans include.
Account, billing, workflows, integrations, and troubleshooting.
## Common questions
You sign in through Clerk, the identity provider ModuleX uses. The first time you sign in, ModuleX creates your account and a personal starter organization for you automatically, so you always have somewhere to work right away. See the [quickstart](/get-started/quickstart) for the full first-run walkthrough.
Open your account's API keys settings and create a key. It starts with `mx_live_` and the full secret is shown only once, at creation time, so copy it immediately and store it somewhere safe. ModuleX keeps only a hashed copy and a short hint, so a lost key cannot be recovered — you delete it and make a new one. Step-by-step instructions are in the [quickstart](/get-started/quickstart).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4500 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The API keys settings screen in the ModuleX app, showing the create-key flow and a newly generated key displayed once.
**[SCREENSHOT_DETAILS]:** Capture the account API-keys settings page. Show the "Create API key" form (name field, optional organization scope, optional expiry, rate-limit field) and the success state where the full `mx_live_*` key appears once with a copy button. Redact the real secret. Light mode, 16:9, annotate the "copy now — shown once" callout and the masked hint (`mx_live_2J9vK4xM********`).
Two fast paths: run the [quickstart](/get-started/quickstart) to make your first authenticated request, or [make your first API call](/get-started/first-api-call) to run a workflow and stream its result. If you would rather click than code, open the workflow builder in the app and run a sample workflow.
Use whichever fits the task — they all reach the same backend. Build visually in the web app, or do the same things from code with the REST API or the JavaScript and Python SDKs. Many people build in the app and then automate with the [API](/get-started/first-api-call).
Yes. The Free plan includes a one-time batch of 300 trial credits so you can try ModuleX before paying — no card required. Paid plans add a recurring monthly credit allowance: Pro includes 5,000 credits per month and Max includes 20,000 credits per month. Compare them on [plans & pricing](/billing/plans).
Pro and Max can also be billed annually. The annual amount shown in marketing may differ from the amount charged at checkout, so confirm the exact yearly price at checkout. See [plans & pricing](/billing/plans).
---
# Knowledge (RAG) — help
URL: https://docs.modulex.dev/help/knowledge-rag
Quick answers for using your own documents in ModuleX: set up a knowledge base, search it from a workflow, what it costs, indexing time, file types and limits, and deleting documents.
Short answers to the questions people ask most about connecting your own documents to ModuleX so your chats and workflows can answer from them. For the full detail, follow the link in each answer.
Manage the knowledge bases that power retrieval across chats and workflows.
The mental model: ingest, embed, retrieve, and answer from your own content.
Upload, watch processing, and remove documents and their chunks.
A step-by-step walkthrough from empty base to first answer.
## Knowledge (RAG)
Create a knowledge base in the app, then upload documents to it. Each file is parsed, split into chunks, and indexed automatically — no setup beyond the upload. Creating and managing knowledge bases needs an owner or admin role. See [Knowledge overview](/platform/knowledge/overview) for the walkthrough.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4550 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** the knowledge base screen in the ModuleX app, with the create-base action and an uploaded document list
**[SCREENSHOT_DETAILS]:** capture the Knowledge area in the ModuleX app for an org that has one knowledge base with a few documents in mixed states; show the create-knowledge-base button and a document showing its processing status; light mode; 16:9; no real customer data
Add a [Knowledge node](/workflow-builder/nodes/knowledge), pick the knowledge base it should search, and give it a search query. The node returns the matching passages so a later node can answer from them. You can also ask questions in [chat with your knowledge](/platform/chat/knowledge-chat).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4551 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** a Knowledge node selected on the workflow canvas with its knowledge base and query fields shown
**[SCREENSHOT_DETAILS]:** capture the workflow builder in the ModuleX app with a Knowledge node selected; show the detail panel where you pick the knowledge base and enter the search query; light mode; 16:9; no real customer data
For ModuleX-managed knowledge, yes — each search and each document you add draws down credits (one credit each, plus the model cost of embedding the text). If you bring your own embedding key (BYOK), that usage is billed by your provider and is not charged in ModuleX credits. See [Credits & metering](/billing/credits).
A newly uploaded document has to finish indexing before it can be searched — it moves from `pending` to `processing` to `completed`. Until it reaches `completed`, its content will not show up in results. Once indexing finishes, later searches are fast. You can watch each document's status in [Managing documents](/platform/knowledge/documents).
Common document types are supported: `pdf`, `docx`, `doc`, `txt`, `md`, `html`, `csv`, `json`, `xlsx`, and `pptx`. The per-file size cap and the number of knowledge bases you can create depend on your plan, not a single fixed limit — see [Managing documents](/platform/knowledge/documents) and [Plans & pricing](/billing/plans).
Yes — remove a document from its knowledge base and its indexed chunks are deleted with it. Deleting is permanent, so the content stops appearing in results right away. See [Managing documents](/platform/knowledge/documents).
Knowledge bases, documents, and search all require an owner or admin role on the organization. If a teammate cannot see or change a knowledge base, check their role under [Account & access](/help/account-access).
## Related help
Connect a provider key for BYOK embeddings or external vector stores.
What managed search and ingest cost, and how usage is measured.
What a `402` or `403` means and how to clear it.
---
# Known limitations — help
URL: https://docs.modulex.dev/help/known-limitations
Plain-language answers about the things to know in ModuleX today: deleting one node at a time, templates not yet available, reconnecting OAuth, owner/admin-only features, the annual price at checkout, and empty install extras.
A few things in ModuleX work differently than you might expect, or are not ready yet. None of them block your work — each has a simple thing to do instead. This page answers the questions people ask most, in plain language.
Looking for the full developer reference, with the reason behind each item and the supported workaround? See [Known limitations](/reference/known-limitations).
Multi-select delete can miss some nodes — remove them one by one.
The template gallery isn't shipped — build directly or use the Composer.
If a connection breaks, disconnect and reconnect it.
Composer, the Assistant, and schedules require an owner or admin.
The yearly amount can differ — check the total at checkout.
`pip` extras add nothing yet — install the base package.
## Common questions
Selecting several nodes on the canvas and deleting them in one go can leave some of them behind. Delete nodes **one at a time** and confirm each one is gone before removing the next. The full explanation is in the [known limitations reference](/reference/known-limitations), and you can learn more about co-editing in [realtime co-editing & external sync](/workflow-builder/realtime-coediting).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4600 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The workflow builder canvas showing several nodes selected, with a caption that only one was removed after a multi-delete.
**[SCREENSHOT_DETAILS]:** Capture in the live ModuleX builder. Show 3 nodes multi-selected (selection outline) in one frame and a second frame after a delete where 2 remain. Annotate "delete one node at a time". Dark mode, 16:9.
Templates aren't available yet — the gallery isn't shipped, so don't plan a workflow around it. Build your workflow directly in the [workflow builder](/workflow-builder/overview), or describe what you want and let [AI Composer in the builder](/workflow-builder/composer) generate it for you. See the [known limitations reference](/reference/known-limitations) for the canonical status.
The in-app button that refreshes an OAuth connection can fail. When a connection breaks, **disconnect the credential and reconnect it** — reconnecting runs the sign-in flow again and issues fresh tokens. See [credentials & integrations help](/help/credentials-integrations) for the reconnect steps and the [known limitations reference](/reference/known-limitations) for why this happens.
These features need an **owner or admin** — a regular member can't run them (the `member` role has been retired). Promote your teammate to owner or admin, or run the action from an owner/admin account. For the full permission model, see [roles & permissions](/security/roles-permissions) and [account & access help](/help/account-access).
The yearly price shown in marketing can differ from the amount you're actually charged, so always **confirm the total on the checkout page** before subscribing annually. Monthly prices are consistent; only the annual figure can disagree. See [plans & pricing](/billing/plans) and [billing, plans & credits help](/help/billing-credits) for both figures side by side.
Not yet — `pip` extras such as `modulex-integrations[all]` or `modulex-integrations[github,slack]` are empty and add nothing beyond the core package. Install the base package, then add any extra dependencies a specific tool needs yourself. See [installing & using integrations](/integrations/install) and the [known limitations reference](/reference/known-limitations) for details.
```bash Do this
# Install the base package (core dependencies only)
pip install modulex-integrations
```
```bash Not this
# These extras are empty / undefined today — they warn and add nothing
pip install "modulex-integrations[all]"
pip install "modulex-integrations[github,slack]"
```
Hit something that isn't here? Check [errors & troubleshooting help](/help/errors-troubleshooting) first, then [get in touch](/help/getting-help).
---
# Realtime collaboration — help
URL: https://docs.modulex.dev/help/realtime-collaboration
Answers to common questions about co-editing a ModuleX workflow with your team: live cursors and presence, edit conflicts and how to re-sync, locking a node, and what happens to your locks when you disconnect.
Work on the same workflow as your teammates, at the same time. This page answers the questions people ask most about live co-editing in the [Workflow Builder](/workflow-builder/overview).
If you want the full picture, two pages go deeper:
The friendly tour of live co-editing: cursors, presence, node locks, and automatic saving.
The reference behind it: every realtime event, payload, timing, and edge case.
## Frequently asked questions
Yes. When two or more people open the same workflow, everyone edits the same live canvas at once — you see each other's cursors move, watch nodes appear and connect, and know who is working where, each person in their own color. Editing is available to the **owner** and **admin** roles; the `member` role is retired and read-only. See [Co-edit a workflow canvas](/platform/collaboration/canvas).
Your view fell too far behind the latest version of the workflow — usually after a burst of edits or a change made outside the canvas (for example by the [AI Composer](/concepts/ai-composer) or the API). When that happens, leave and re-join the workflow to re-sync with the current state, then continue editing. See [Presence, locks & versioning](/realtime/presence-locks).
Yes. Lock a node and you become its holder; everyone else sees it as held by you and cannot edit it until you release it. A lock also releases on its own after about five minutes of inactivity, so a node is never stuck. See [Presence, locks & versioning](/realtime/presence-locks).
Any node locks you were holding are released automatically and your presence disappears for everyone else. Nothing you saved is lost — edits are saved in the background as you work. Just re-open the workflow to rejoin and continue. See [Co-edit a workflow canvas](/platform/collaboration/canvas).
Co-editing is a feature of the **app** — it works automatically whenever two people open the same workflow, with nothing to turn on and no API or SDK call involved.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4570 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** Short walkthrough answering the four collaboration FAQs in order: co-editing, an edit conflict and re-sync, locking a node, and a disconnect releasing locks.
**[APP_VIDEO_DETAILS]:** Side-by-side screen recording of two browser sessions (User A "Ada" and User B "Lin") with the same workflow open. Show, in order: (1) B's presence avatar and colored cursor appearing on A's canvas as both edit; (2) A getting an edit conflict and re-joining the workflow to re-sync to the current state; (3) B locking a node and A seeing a "being edited by Lin" badge, then B releasing it; (4) B's tab closing and B's locks and presence clearing on A's canvas. 16:9, light theme, ~30s, annotate the presence avatars, the conflict/re-sync moment, and the lock badge.
## Related help
Building, running, and watching workflows.
Organizations and the owner/admin roles that can edit.
---
# Workflows & runs — help
URL: https://docs.modulex.dev/help/workflows-runs
Answers to common questions about building and running workflows in ModuleX: the nine node types, passing data with node references, pausing for input, cancelling a run, and watching a run live.
A workflow is a graph of steps you connect on a canvas; a run is one execution of that workflow. This page answers the questions people ask most often when building and running workflows.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4530 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** Building and running a workflow end to end in the Workflow Builder.
**[APP_VIDEO_DETAILS]:** Screen recording of the live ModuleX app. Show adding two or three nodes to the canvas, connecting them, saving, deploying, then clicking Run and watching the live run stream. End on a completed run. 60-90s, 16:9, light mode, with short caption annotations on each step.
## Quick links
Where you build workflows on the visual canvas.
The nine node types and what each one does.
## Common questions
Open the [Workflow Builder](/workflow-builder/overview), add nodes to the canvas, connect them in the order you want them to run, then save and deploy. Click Run to execute it in the app, or trigger it from the API. See [running workflows](/workflow-builder/execution/running) for the in-app run view and [run via API](/workflow-builder/execution/api-endpoint) to trigger one from code.
There are nine node types: LLM, Tool, Function, Agent, Conditional, Interrupt, Transformer, Guardrails, and Knowledge. Each one does a different kind of work in a run. The [node types overview](/workflow-builder/nodes/overview) explains what each does and when to use it.
Reference an earlier node's output with the `{{node_id.field}}` syntax — for example, `{{search.results}}` pulls the `results` value from the node with the id `search`. Every node writes its result into the run under its own id, so any later node can read it. See [variables & references](/workflow-builder/variables-and-references).
Yes. Add an Interrupt node where you want the run to wait. When the run reaches it, the run pauses, asks your question, and waits for an answer before continuing. See the [Interrupt node](/workflow-builder/nodes/interrupt).
Cancel it from the run view in the app, or call the cancel endpoint from code. Cancellation is graceful: the run stops after the current node finishes, not mid-step. Only runs that are still running or paused can be cancelled. See [running workflows](/workflow-builder/execution/running).
Stream it. In the app, the run view shows each step as it happens. From code, open the run's event stream — in the SDKs this is the `listen()` method, which yields events as they occur until the run finishes. See [running workflows](/workflow-builder/execution/running).
## Run a workflow from code
When you trigger a run, ModuleX returns immediately with the run details, then you open a separate stream to watch progress. Authenticate every request with `Authorization: Bearer mx_live_…` and the `X-Organization-ID` header. In the SDKs, pass your API key and organization id when you create the client.
```bash cURL
# 1. Start the run — returns immediately with a run_id
curl -X POST https://api.modulex.dev/workflows/run \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: org_your_org_id" \
-H "Content-Type: application/json" \
-d '{
"workflow_id": "wf_29ab83c1",
"input": { "topic": "release notes" }
}'
# 2. Watch it live over the event stream
curl -N https://api.modulex.dev/workflows/listen/run_7k8l9m0n \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: org_your_org_id"
# 3. Cancel it (graceful — stops after the current node)
curl -X POST https://api.modulex.dev/workflows/cancel/run_7k8l9m0n \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: org_your_org_id" \
-H "Content-Type: application/json" \
-d '{ "reason": "User requested cancellation" }'
```
```python Python
from modulex import Modulex
client = Modulex(
api_key="mx_live_your_api_key",
organization_id="org_your_org_id",
)
# 1. Start the run
run = await client.executions.run(
workflow_id="wf_29ab83c1",
input={"topic": "release notes"},
)
# 2. Watch it live — listen() yields events until the run finishes
async for event in client.executions.listen(run.run_id):
print(event["type"])
# 3. Cancel it (graceful)
await client.executions.cancel(run.run_id, reason="User requested cancellation")
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_your_api_key",
organizationId: "org_your_org_id",
});
// 1. Start the run
const run = await client.executions.run({
workflowId: "wf_29ab83c1",
input: { topic: "release notes" },
});
// 2. Watch it live — listen() yields events until the run finishes
for await (const event of client.executions.listen(run.runId)) {
console.log(event.type);
}
// 3. Cancel it (graceful)
await client.executions.cancel(run.runId, { reason: "User requested cancellation" });
```
Running a workflow on ModuleX-managed models and tools consumes credits, and the run is blocked if your organization is out of credits. See [usage gating & limits](/billing/usage-gating) and [errors & troubleshooting](/help/errors-troubleshooting).
## Related help
Generate a workflow from a plain-English prompt, or let the Assistant work step by step.
What common errors mean and how to fix a failed run.
---
# ModuleX documentation
URL: https://docs.modulex.dev/
Build, run, and automate AI workflows with ModuleX — the no-code canvas, AI Composer, managed knowledge (RAG), 175 integrations, and a developer API with JavaScript and Python SDKs.
ModuleX is an AI workflow orchestration platform. You describe a process in plain
language or draw it on a visual canvas, connect the tools and data you already
use, and run it with any major AI model — from chat, the API, or an SDK.
There are two ways to work with ModuleX, and you can mix them freely.
Build workflows on a collaborative visual canvas, generate them from a prompt
with the [AI Composer](/concepts/ai-composer), and chat with the agentic
[Assistant](/concepts/assistant) — no engineering required.
Run the same workflows from your own software with the REST API or the
official [JavaScript](/sdks/javascript) and [Python](/sdks/python) SDKs.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-1000 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** A 60-second product tour of the ModuleX app, from a prompt to a running workflow.
**[APP_VIDEO_DETAILS]:** Screen recording of the live app. Show: (1) opening the AI Composer and typing a plain-English request, (2) the Composer laying out nodes on the canvas, (3) a teammate's cursor co-editing the same canvas, (4) running the workflow and watching the live stream of node updates. ~60s, 16:9, dark theme to match the docs, no audio narration required, light captions for each step.
## Start here
Pick the path that matches how you want to begin.
Create an account, get an API key, and make your first authenticated call.
Build a workflow in the canvas or with the Composer, then run it from the app.
Trigger a workflow from code in cURL, Python, or JavaScript.
## Explore the docs
The mental model behind ModuleX: workflows and runs, the workflow engine and
its nodes, the Composer and Assistant, knowledge and RAG, organizations, and
credits.
The request lifecycle, authentication, errors, and every operation shown once
in cURL, Python, and JavaScript — plus a live endpoint playground.
Connect ModuleX to 175 services and call their tools from workflows and the
Assistant.
A tour of the app: chat, the workflow builder, knowledge bases, realtime
collaboration, and the agentic Assistant.
## What you can do with ModuleX
The [AI Composer](/concepts/ai-composer) turns a plain-English description
into an editable workflow graph — steps, tools, and logic laid out on the
canvas for you to refine.
Multiple people can edit the same [workflow builder](/workflow-builder/overview)
canvas at once, with live cursors, presence, and node locks.
Connect documents to a [knowledge base](/platform/knowledge/overview) and let
workflows and chat retrieve the right context automatically with RAG.
The [Assistant](/assistant/overview) is an agentic chat that searches your
connected tools, drafts outputs, and pauses for approval before sensitive
actions — no workflow required.
## Run a workflow from code
Every workflow you build in the app can be triggered programmatically. Each
request authenticates with an API key in the `Authorization` header and selects
your organization with the `X-Organization-ID` header.
```bash cURL
curl https://api.modulex.dev/workflows/run \
-H "Authorization: Bearer mx_live_4f8c2a1b9e7d6c5b4a3f2e1d0c9b8a7f" \
-H "X-Organization-ID: org_3a7f19e2c4b8" \
-H "Content-Type: application/json" \
-d '{
"workflow_id": "wf_9c1d4e7a2b6f",
"input": { "topic": "quarterly sales summary" },
"stream": true
}'
```
```python Python
import asyncio
from modulex import Modulex
async def main():
client = Modulex(
api_key="mx_live_4f8c2a1b9e7d6c5b4a3f2e1d0c9b8a7f",
organization_id="org_3a7f19e2c4b8",
)
run = await client.executions.run(
workflow_id="wf_9c1d4e7a2b6f",
input={"topic": "quarterly sales summary"},
stream=True,
)
print(run.run_id, run.status)
await client.close()
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from 'modulex-js';
const client = new Modulex({
apiKey: 'mx_live_4f8c2a1b9e7d6c5b4a3f2e1d0c9b8a7f',
organizationId: 'org_3a7f19e2c4b8',
});
const run = await client.executions.run({
workflowId: 'wf_9c1d4e7a2b6f',
input: { topic: 'quarterly sales summary' },
stream: true,
});
console.log(run.run_id, run.status);
```
Running a saved workflow requires an active deployment. Managed runs pass through
ModuleX's billing gate and can return a `402`, `403`, or `429` denial when your
plan's credits or limits are reached. See
[errors & status codes](/api-reference/errors) and
[usage gating & limits](/billing/usage-gating).
For the full walkthrough — authenticate, run, and stream the result in three
languages — see [Run a workflow (REST + SDK)](/guides/run-a-workflow).
## How billing works, in one line
Managed usage is metered in **credits**: 100 credits equal $1.00. Each plan
includes a monthly credit allowance, and paid organizations can add a prepaid
wallet for usage beyond it. If you bring your own model and tool keys (BYOK), that
usage is billed directly by the provider and is not credited. See
[billing & credits overview](/billing/overview) and
[plans & pricing](/billing/plans).
## Get help
Short answers for getting going, using ModuleX, and troubleshooting.
Canonical ModuleX terminology in one place.
Documented gaps and paths you should not rely on yet.
---
# Integration authentication & credentials
URL: https://docs.modulex.dev/integrations/authentication
How ModuleX integrations authenticate: the six auth schema variants, the OAuth2 PKCE connect flow, encryption at rest, and how credentials are resolved at run time.
Every integration in ModuleX needs a way to prove who it is to the service it
calls. An integration declares the auth methods it supports in its manifest; you
supply the secret once, ModuleX encrypts it, and the runtime resolves and decrypts
it on every tool call. This page is the exhaustive reference for that contract: the
six auth schema variants a manifest can expose, the OAuth2 authorization-code flow
with PKCE, how secrets are encrypted at rest, and the precedence rules that pick a
credential at run time.
For the conceptual model and a guided OAuth walkthrough, see
[Credentials & OAuth2](/concepts/credentials-oauth). To create, set defaults for,
test, and delete credentials in the app and over the API, see
[Managing credentials](/integrations/managing-credentials).
A credential is **organization-scoped**, never user-scoped. Every credential
belongs to one organization and is encrypted, resolved, and billed against that
org. All credential endpoints require the **owner** or **admin** role
(`organization_admin_required`); the `member` role is retired. The org is selected
by the `X-Organization-ID` header on every request — see
[Org context & X-Organization-ID](/security/org-context).
## The six auth schema variants
An integration manifest exposes one or more **auth schemas** under
`auth_schemas`. The list is a discriminated union keyed on `auth_type`, so each
entry is exactly one of six variant classes. A single integration may ship several
(GitHub ships both OAuth2 and a bearer-token personal-access-token option; Exa ships
both an API key and a ModuleX-managed key).
| `auth_type` | Variant class | What you supply | Typical use |
| --- | --- | --- | --- |
| `oauth2` | `OAuth2AuthSchema` | Nothing directly — you complete a consent flow | GitHub, Google Calendar, Netlify |
| `bearer_token` | `BearerTokenAuthSchema` | A long-lived token (e.g. a personal access token) | GitHub PAT |
| `api_key` | `ApiKeyAuthSchema` | A provider-issued API key | Exa, ConvertAPI, Hunter, Freshdesk |
| `modulex_key` | `ModulexKeyAuthSchema` | Nothing — ModuleX supplies a managed key, billed in credits | Exa (managed), Firecrawl, Jina AI, Hacker News |
| `custom` | `CustomAuthSchema` | Free-form fields defined by the integration | PostgreSQL, WooCommerce, Coinbase |
| `internal` | `InternalAuthSchema` | Reserved — not supplied by you | System-managed only |
`internal` is a **reserved/forward** variant. It is a valid `auth_type` and a
defined schema class, but no shipped integration in the catalog uses it, and
`internal` credentials are excluded from credential listings (they back
system-managed resources such as the managed knowledge store). Treat it as
read-only and do not author manifests against it.
There is one casing edge case to know about. The integration manifest schema
defines **six** `auth_type` values. The backend credential table's CHECK
constraint allows **seven** — it additionally accepts a legacy `bearer` value with
no corresponding manifest variant. New integrations must emit only the six schema
variants above; `bearer` is a legacy database value, not a manifest option.
### Shared fields on every variant
Every auth schema, regardless of `auth_type`, inherits the same base fields.
Human-readable label shown in the connect UI (e.g. `"OAuth2 Authentication"`).
One-line explanation of the method shown next to the label.
An ordered list of steps shown to the person connecting the integration (e.g. how
to create a personal access token).
Operator- or user-supplied secrets and settings for this method. See
[`EnvVar`](#envvar-operator-or-user-supplied-values) below.
An optional HTTP call the runtime makes to validate a configured credential. Some
`modulex_key` public-API integrations ship none, in which case credential testing
is skipped. See [`TestEndpoint`](#testendpoint-credential-validation).
### OAuth2 variant (`oauth2`)
`OAuth2AuthSchema` adds a single extra field, `oauth_config`, that describes the
authorization-code flow.
The provider's authorization endpoint the user is redirected to (e.g.
`https://github.com/login/oauth/authorize`).
The provider's token-exchange endpoint where the authorization code is swapped for
tokens (e.g. `https://github.com/login/oauth/access_token`).
OAuth scopes requested at consent (e.g. `["repo", "user", "read:org", "workflow"]`).
A connect request may override these with its own `scope` string.
How the client credentials are presented at token exchange. `body` sends
`client_id`/`client_secret` in the form body (RFC 6749 `client_secret_post`);
`basic` sends them as HTTP Basic auth (used by providers such as Notion).
Extra authorize parameter for providers that need it. Google requires
`"offline"` to issue a `refresh_token`.
Extra authorize parameter. `"consent"` re-issues a refresh token on every
reconnect (Google).
Whether to use PKCE (RFC 7636, S256). On by default. A manifest can set this to
`false` for providers that reject an unexpected `code_verifier` (Netlify does).
**PKCE-opt-out (`use_pkce: false`) may not be honored end to end.** The manifest
field exists, but the runtime is documented as currently hardcoding PKCE on, so a
manifest that sets `use_pkce: false` may still send a `code_verifier`. This is an
[open question](/reference/known-limitations) pending verification against the live
runtime — do not rely on opting out of PKCE until it is confirmed wired. For
providers that accept PKCE (the large majority), the default behavior is correct.
### Bearer-token variant (`bearer_token`)
`BearerTokenAuthSchema` adds no extra fields. You supply a long-lived token (e.g. a
GitHub personal access token). The runtime sends it as
`Authorization: Bearer ` to the service. On the wire the stored
`auth_type` is `bearer_token`.
### API-key variant (`api_key`)
`ApiKeyAuthSchema` adds no extra fields. You supply a provider-issued API key. How
the key is presented (header name, query parameter, etc.) is defined by the
integration's `test_endpoint` and its tool functions, not by a fixed convention.
### ModuleX-managed-key variant (`modulex_key`)
`ModulexKeyAuthSchema` adds no extra fields, and you supply **nothing** — ModuleX
provisions a managed key from a pooled key store. Usage of a `modulex_key`
credential is **metered in credits** and passes through the billing gate at run
time (see [Resolution at run time](#how-credentials-are-resolved-at-run-time)
below and [Credits & metering](/billing/credits)). This is the difference that
matters: a `modulex_key` credential always carries a usage/credit gate; a
credential you supply yourself never does.
### Custom variant (`custom`)
`CustomAuthSchema` adds no extra fields at the schema level. The integration
defines the fields it needs through `setup_environment_variables`, and the connect
UI renders one input per declared `EnvVar`. PostgreSQL (host, port, database, user,
password) is a typical example.
## `EnvVar` — operator- or user-supplied values
Each auth schema can declare a list of `EnvVar` entries under
`setup_environment_variables`. An `EnvVar` is a single secret or setting, and two
of its flags — `only_for_custom` and `inject_into_auth_data` — decide where the
value comes from and whether a tool function can read it.
Env-var-style key (e.g. `GITHUB_OAUTH2_CLIENT_ID`).
Label shown in the UI.
Help text shown under the field.
Whether the value must be supplied. Note this defaults to `true` — the opposite of
`ParameterDef.required`, which defaults to `false`.
Whether the value is a secret. Sensitive values are masked in the UI.
`true` marks the value as a **server-level** secret: the ModuleX-managed app
resolves it from the server environment, while a bring-your-own-app user supplies
their own. Examples: a GitHub OAuth client id/secret, a Google Ads
`developer_token`.
`true` guarantees the value is present in `auth_data` at action-execution time so a
tool function can read it (the key is prefix-stripped and lowercased). `false`
(the default) means the value is used only for OAuth provider config and the test
endpoint, and never reaches a tool call.
Placeholder hint shown in the input (e.g. `"ghp_xxxx..."`).
Link to where the user obtains the value.
The interaction of the two flags determines handling:
| `inject_into_auth_data` | `only_for_custom` | Behavior |
| --- | --- | --- |
| `false` (default) | any | OAuth/test-only; never reaches a tool function. |
| `true` | `false` | Per-credential **user input**, persisted into `auth_data` at credential creation. |
| `true` | `true` | **Server-level secret**; the managed app injects it from server env at resolution time; a BYO-app user supplies their own. |
## `TestEndpoint` — credential validation
When an auth schema declares a `test_endpoint`, ModuleX can validate a credential
by making one HTTP call before relying on it. Placeholders in the URL, headers,
params, or body — such as `{access_token}`, `{token}`, `{api_key}`,
`{bearer_token}`, or any `auth_data`/`EnvVar` key — are substituted by the runtime.
The endpoint to call. May embed query placeholders (e.g. `?Secret={api_key}`).
HTTP method for the validation call.
Request headers, with placeholder substitution (e.g.
`{"Authorization": "Bearer {access_token}"}`).
URL query parameters, for query-parameter credentials.
JSON payload for non-GET validation calls.
Declarative HTTP Basic auth. When set, the runtime builds
`Authorization: Basic ` itself and ignores any `Authorization`
header you set. A placeholder that is not an `auth_data` key is treated as a
literal string.
What counts as success: a list of acceptable `status_codes` (e.g. `[200]`) and an
optional list of `response_fields` that must appear in the response body (e.g.
`["login", "id"]`).
Free-form cost hint. Observed values include `"free"` and `"minimal"`; the schema
does not constrain the set.
Human-readable note describing what the validation checks.
When you test a credential, the response reports `test_method`, which is one of
`api_call` (an actual request was made), `basic`, or `none` (the integration ships
no `test_endpoint`, so testing is skipped and the credential is treated as valid).
See [Managing credentials](/integrations/managing-credentials) for the full
test-and-save flow.
## How an integration reads the credential
A tool function receives its credential through one of two run-time conventions,
chosen by the auth type:
- **Token-based** (`oauth2`, `bearer_token`) — the function signature leads with
`auth_type: str, auth_data: dict[str, Any]`, then its action parameters. It
builds request headers from `(auth_type, auth_data)`.
- **Key-based** (`api_key`, `modulex_key`) — the function takes the action
parameters plus `api_key: str` directly (often sent as `x-api-key: {api_key}`),
and checks the key is non-empty before calling out.
This is part of the `@tool` function contract; for the full decorator order, output
models, and worked examples, see
[The @tool function contract](/integrations/building/tool-contract) and
[Manifest & schema contract](/integrations/building/manifest-schema).
## The OAuth2 connect flow (PKCE)
OAuth2 integrations are connected through an authorization-code flow with PKCE. You
never paste a token; ModuleX initiates the flow, the provider redirects the
browser back, and ModuleX exchanges the code and stores the resulting credential.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4020 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** Sequence diagram of the OAuth2 PKCE connect flow.
**[IMAGE_DETAILS]:** Five lanes left to right — User/Browser, ModuleX app (frontend), ModuleX backend, Redis (5-min state store), OAuth provider. Show: (1) `POST /credentials/oauth2/initiate` returning `authorization_url` + `state`, with `code_verifier`/`code_challenge` (S256) generated and flow state written to Redis with a 5-minute TTL; (2) browser redirected to the provider, user consents; (3) provider redirects browser to `GET /credentials/oauth2/callback?code&state`; (4) backend one-time reads + deletes the Redis `state`, exchanges code at `token_url` (PKCE `code_verifier`), encrypts and stores the credential; (5) backend issues a 302 back to the frontend landing page with `?status=success&credential_id=`. Annotate the 5-minute TTL and the one-time state read. Light theme, 16:9.
### Step 1 — initiate
`POST /credentials/oauth2/initiate` starts the flow. The backend loads the
integration's `oauth2` schema, builds the authorization URL (generating a PKCE
`code_verifier` and S256 `code_challenge`), stores the flow state in Redis with a
**5-minute TTL**, and returns the URL for the browser to open.
The integration to connect. Must expose an `oauth2` auth schema, or the request
fails with `400`.
`true` uses the ModuleX-registered OAuth app for the provider (the managed path).
`false` uses your own OAuth app and requires `custom_oauth_config`.
Required only when `use_modulex_oauth` is `false`. Must contain `client_id` and
`client_secret` for your own OAuth app. The `auth_url`/`token_url` come from the
integration schema.
The callback URL the provider redirects to after consent. This is the ModuleX
backend callback (e.g. `https://api.modulex.dev/credentials/oauth2/callback`).
Space-separated scopes. Defaults to the provider/schema scopes joined by spaces.
A label for the credential that gets created.
Whether the new credential becomes the default for its integration.
Per-user `EnvVar` values (string-to-string). Only values whose `EnvVar` has
`inject_into_auth_data: true` and `only_for_custom: false` are folded into the
persisted `auth_data`.
Composer auto-resume linkage. Must be supplied together with
`composer_request_id` and `composer_llm_config`; supplying some but not all returns
`400`.
Composer auto-resume linkage — see `composer_chat_id`.
Composer auto-resume linkage — see `composer_chat_id`.
Authenticate with a key or a Clerk JWT plus the org header, exactly as for any
ModuleX API call (see [Authentication](/api-reference/authentication)):
```bash cURL
curl -X POST https://api.modulex.dev/credentials/oauth2/initiate \
-H "Authorization: Bearer mx_live_abc123" \
-H "X-Organization-ID: 8f2c1d9e-0000-4a11-9c3d-2b6e7f4a1234" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "github",
"use_modulex_oauth": true,
"redirect_uri": "https://api.modulex.dev/credentials/oauth2/callback",
"display_name": "Production GitHub",
"make_default": true
}'
# → {"authorization_url": "https://github.com/login/oauth/authorize?...", "state": ""}
```
```python Python
import os
import httpx
resp = httpx.post(
"https://api.modulex.dev/credentials/oauth2/initiate",
headers={
"Authorization": f"Bearer {os.environ['MODULEX_API_KEY']}",
"X-Organization-ID": "8f2c1d9e-0000-4a11-9c3d-2b6e7f4a1234",
},
json={
"integration_name": "github",
"use_modulex_oauth": True,
"redirect_uri": "https://api.modulex.dev/credentials/oauth2/callback",
"display_name": "Production GitHub",
"make_default": True,
},
)
data = resp.json() # {"authorization_url": "...", "state": "..."}
```
```javascript JavaScript
const resp = await fetch(
"https://api.modulex.dev/credentials/oauth2/initiate",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.MODULEX_API_KEY}`,
"X-Organization-ID": "8f2c1d9e-0000-4a11-9c3d-2b6e7f4a1234",
"Content-Type": "application/json",
},
body: JSON.stringify({
integration_name: "github",
use_modulex_oauth: true,
redirect_uri: "https://api.modulex.dev/credentials/oauth2/callback",
display_name: "Production GitHub",
make_default: true,
}),
},
);
const data = await resp.json(); // { authorization_url, state }
```
The provider authorize URL to open in the browser. Includes the `state` and PKCE
`code_challenge`.
A one-time CSRF/correlation token. ModuleX stores the flow state in Redis keyed by
this value with a 5-minute TTL.
Connecting an OAuth2 integration is not directly available through the official
JavaScript and Python SDKs — initiate is a browser-driven flow. The cURL example
above shows the underlying REST call; in the app, the connect UI performs the same
request and opens the consent page for you. See
[Managing credentials](/integrations/managing-credentials).
### Step 2 — provider consent and callback
The browser opens `authorization_url`, the user approves the requested scopes, and
the provider redirects back to the `redirect_uri`, which is the backend callback:
`GET /credentials/oauth2/callback?code=...&state=...`
This endpoint is the only credential route that is **anonymous** — the browser
arriving from the provider carries no ModuleX session. Trust comes entirely from
the one-time Redis `state` value. The callback:
Reads and deletes the Redis `state` (one-time read). If it is missing — expired
past five minutes or already used — the flow ends in an error redirect with
`error_code=invalid_state`.
Posts the authorization code (and PKCE `code_verifier`) to the provider's
`token_url`, presenting client credentials per the schema's `token_auth_method`
(`body` or `basic`). Failure ends in `error_code=token_exchange_failed`.
Assembles `auth_data` (`access_token`, `token_type` defaulting to `bearer`, an
optional `refresh_token`, and `expires_at` derived from `expires_in`), folds in any
injected `EnvVar` values, encrypts it, and creates the credential. The credential
is created with no `created_by` because the call is anonymous.
Always returns a **302** to the frontend landing page — never JSON. On success the
URL carries `?status=success&integration=&credential_id=`; on failure
`?status=error&integration=&error_code=&message=`.
The callback **always** responds with a 302 redirect, even on error, so the app can
show the outcome. Recognized `error_code` values include `oauth_denied`,
`oauth_provider_error`, `missing_params`, `invalid_state`,
`token_exchange_failed`, `credential_creation_failed`, `invalid_credentials`, and
`internal_error`.
### Token refresh — and why you reconnect instead
ModuleX refreshes OAuth2 access tokens **automatically at run time**. When a
credential is resolved for a tool call and its `expires_at` is within five minutes
of expiring, the resolver uses the stored `refresh_token` and decrypted
`oauth_config` to obtain a new access token, re-encrypts the credential, and
continues. You do not trigger this; it happens inside resolution.
**Do not rely on a manual "refresh OAuth" action — it is broken.** The manual
OAuth-refresh path in the app is a known limitation: the frontend route that the
"refresh" control would call does not exist, so the call fails before it reaches
the backend. If an OAuth credential ever needs to be re-established (for example,
the provider revoked the grant, or the credential never received a `refresh_token`
because the provider needs `access_type=offline`/`prompt=consent`), **reconnect the
integration** — run the connect flow again from Step 1, which issues fresh tokens
and updates the credential. See
[Known limitations](/reference/known-limitations).
There is also a behavioral gap to be aware of in automatic refresh. The automatic
in-resolution refresh always presents client credentials in the request body and
ignores the schema's `token_auth_method`. A provider that requires `basic`-auth at
the token endpoint (such as Notion) would fail an automatic refresh with
`invalid_client`; reconnecting re-issues a working credential. This is logged as a
parity gap.
## How credentials are stored (encrypted at rest)
Credentials are never stored in plaintext. ModuleX uses two distinct encryption
schemes depending on what is being protected.
The `auth_data` and `oauth_config` you supply for a credential are encrypted with a
key derived **per credential**:
- The key is derived with HKDF-SHA256 (length 32), scoped to
`(organization_id, credential_id)`, from the server master key `ENCRYPTION_KEY`.
- The data is JSON-serialized and sealed with Fernet (AES-128-CBC + HMAC-SHA256).
Because the key is scoped to the specific organization and credential, ciphertext
cannot be moved between credentials — it fails to decrypt. The master
`ENCRYPTION_KEY` is required in production and must be at least 32 characters
(256 bits).
The ModuleX-registered OAuth app client ids and secrets (used by the managed OAuth
path) are encrypted with PBKDF2-HMAC-SHA256 (length 32, 100000 iterations) using a
**random 16-byte salt per value**, then sealed with Fernet. The output is
`base64url(salt || fernet_token)`. Decryption tries the salt-prepended format
first and falls back to a legacy static salt for older values.
Each encrypted table carries an `encryption_key_version` column that defaults to
`1` — scaffolding for future key rotation; it is currently always `1`. When a
credential is read back, secrets are **masked**, never returned in clear: an
`oauth2` credential reports the literal label `OAuth2`; an `api_key` reports a
masked key; a `bearer_token`/`bearer` reports a masked token; anything else reports
`Credential`.
For the broader encryption and key-management posture, see
[Data security & encryption](/security/data-encryption).
The `modulex_key` (ModuleX-managed) credential stores only a **UUID** in its
encrypted blob, not a real provider key. The UUID points into a system-managed key
pool; the real key is fetched from the pool at resolution time and is never
persisted on your credential. See the resolution rules below.
## How credentials are resolved at run time
When a tool or LLM node executes, ModuleX resolves a credential in two phases:
**pick** one, then **prepare** it for execution (decrypt, refresh, and — for
managed keys — gate on credits).
### Phase A — pick a credential
If the caller passes a `credential_id`, that exact credential is used. It must
belong to the org and match the integration; otherwise resolution fails with "no
credential found."
If no id is given, the credential marked `is_default` for the
`(organization, integration_name, integration_type)` is used.
If there is no default, ModuleX falls back to any valid credential, ordered to
prefer a **user credential over a `modulex_key`**, then most recent first.
If nothing valid is found, resolution fails with "no credential found."
**Precedence summary:** explicit `credential_id` > `is_default` row > most-recent
valid **user** credential > most-recent valid `modulex_key`.
### Phase B — prepare for execution
The prepare step differs by whether the chosen credential is a managed key or one
you supplied.
1. Decrypt `auth_data`.
2. If `auth_type` is `oauth2`, refresh the access token when it is within five
minutes of expiring (re-encrypt, update, commit, and clear the Redis cache for
the credential). This needs a `refresh_token` and the decrypted `oauth_config`.
3. Return the decrypted `auth_data` for the tool function to use.
**No credit check applies to user credentials.** Usage of a credential you supply
is not metered in ModuleX credits — the provider bills you directly (BYOK).
1. Decrypt the stored blob, which holds a `modulex_key` UUID (not a real key).
2. Verify that UUID is registered for the `(organization, integration, key)` — if
not, resolution fails with a verification error.
3. Fetch the **real** API key from the system key pool.
4. **Check the credit limit** for the org. The check happens here, before
execution. If the org is over its limit, resolution raises a credit-limit
error; with no active subscription it raises a resolution error.
5. Return `auth_data` containing the real key. For `tool` integrations, post-
execution usage logging is required so the call can be billed.
A `modulex_key` credential **always** carries this credit gate — see
[Usage gating & limits](/billing/usage-gating) and
[Credits & metering](/billing/credits).
## Errors
Credential CRUD and OAuth endpoints raise the standard FastAPI
`HTTPException` envelope — `{"detail": }` — for everything except the
org-level rate-limit deny, whose `detail` is a dict. These routes do **not** emit
the flat `DenialEnvelope`; the credit gate fires inside credential *resolution* at
run time, not on these CRUD routes. For the full taxonomy of all three error
envelope shapes and which surface emits each, see
[Errors & status codes](/api-reference/errors).
| Status | When |
| --- | --- |
| `201` | Credential created. |
| `204` | Credential deleted. |
| `302` | OAuth2 callback — always a redirect back to the app, even on error. |
| `400` | Missing `X-Organization-ID`; invalid `auth_data`/`auth_type`; integration has no OAuth2 schema; missing/partial composer linkage; invalid custom OAuth config. |
| `401` / `403` | Not authenticated; not a member; not owner/admin. |
| `404` | Integration or credential not found. |
| `429` | Org-class `api` rate limit (fail-open); includes `X-RateLimit-*` and `Retry-After` headers. |
| `500` | Unexpected error during create/test. |
| `503` | OAuth state storage (Redis) unavailable at initiate. |
There is **no `402`** on these credential routes. A `402` from credit exhaustion
appears on the **run / composer / assistant / managed-knowledge** surfaces when a
`modulex_key` credential is resolved during execution — that is where the credit
gate is enforced. See [Usage gating & limits](/billing/usage-gating).
## Next steps
The conceptual model and a guided walkthrough of connecting an OAuth integration.
Create, set defaults for, test, and delete credentials in the app and over the API.
The full pydantic contract behind the six auth schema variants.
How ModuleX encrypts credentials and manages keys.
---
# Custom MCP servers
URL: https://docs.modulex.dev/integrations/building/custom-mcp
Connect an external Model Context Protocol (MCP) server to ModuleX as a credential, auto-discover its tools, and call them from workflows and agents. Exhaustive reference: the three REST routes, every request and response field, the discovery metadata shape, transport and auth, error envelopes, and SDK equivalents.
A **Model Context Protocol (MCP) server** is an external service that exposes a
set of tools over a standard wire protocol. ModuleX can connect to one as a
**credential**, discover the tools it advertises, and make those tools callable
from a [Tool node](/workflow-builder/nodes/tool), the [AI Composer](/concepts/ai-composer),
and the [Assistant](/assistant/overview) — exactly like a built-in catalog
integration, but without writing any code.
This is the second of the two ways to add tools to ModuleX. The first is to
author a package integration with the `@tool` contract (see
[Build an integration](/integrations/building/overview)). Connecting an MCP
server is the lighter-weight path: you point ModuleX at a server URL, it lists
the server's tools, and it stores them on a credential your organization can use.
There is **no in-app builder for authoring integrations** today. You add your
own tools either by publishing a package to the `modulex-integrations` catalog
(code) or by connecting an external MCP server (this page). Both paths are
code/configuration only.
## How it works
When you register an MCP server, ModuleX connects to it once, lists its tools,
and persists the connection plus the discovered tool definitions as a single
credential. At run time, a [Tool node](/workflow-builder/nodes/tool) that
references that credential reconnects to the server, loads the live tools, and
invokes the one you named.
Call `POST /credentials/mcp-server` with the server URL (and any auth
headers). ModuleX connects, discovers the tools, and stores them on a new
credential whose `integration_name` is the literal `mcp_server` and whose
`auth_type` is `custom`.
The create response includes the discovered tools in
`credentials_metadata`. You can also read them any time with
`GET /credentials/{credential_id}/mcp-tools`.
In a [Tool node](/workflow-builder/nodes/tool), set
`tool.integration_name` to `mcp_server`, set `tool.credential_id` to your
MCP credential, and set `tool.service_name` to the MCP tool's name.
When the server adds or removes tools, call
`POST /credentials/{credential_id}/refresh-discovery` to re-list and update
the stored tool definitions.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4200 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** Diagram of the MCP credential lifecycle in ModuleX.
**[IMAGE_DETAILS]:** Three-stage flow — (1) `POST /credentials/mcp-server` → ModuleX connects to the external MCP server and discovers tools; (2) tools stored on an `mcp_server` credential (`auth_type: custom`) in the organization; (3) a Tool node references the credential by `credential_id` and `service_name`, ModuleX reconnects at run time and invokes the tool. Show the server URL masked. Light theme, 16:9, labelled arrows.
## What a discovered tool looks like
Each tool ModuleX discovers is reduced to three fields, captured at discovery
time and stored on the credential:
The MCP tool's name, as advertised by the server. This is the value you put in
a Tool node's `service_name`.
The tool's human/LLM-facing description (empty string if the server provides
none).
The tool's input parameters as a JSON Schema object (typically
`{type, properties, required}`). ModuleX reads this from the tool's
`args_schema` (or `args` / `tool_call_schema` fallbacks); if the server
advertises no schema, this is an empty object `{}`.
At run time, ModuleX parses each tool's MCP `TextContent` response — a shape like
`[{"type": "text", "text": "{...}"}]` — and decodes the stringified JSON so that
an MCP tool returns structured data just like a built-in tool. This parsing is
handled internally by `MCPToolWrapper`; you do not configure it.
## Transport and protocol
ModuleX connects to the server with the `langchain-mcp-adapters` client over a
configurable transport. Two transports exist in the protocol — `sse` and
`streamable_http` — but the **REST route does not expose a transport field**: a
server registered through `POST /credentials/mcp-server` always uses the default
**`streamable_http`** transport. The discovered `server_info.protocol_version`
ModuleX records is `2024-11-05`.
Because the create route fixes the transport to `streamable_http`, an MCP server
that speaks only the older `sse` transport cannot currently be registered
through the public API. If you need `sse`, raise it with support — it is set on
the stored credential's `auth_data`, not on the request body. (TBD: a public
way to choose the transport at registration time.)
## Authentication
Every ModuleX API request authenticates with your API key as a bearer token plus
your organization context header. See
[API authentication](/api-reference/authentication) for the full model.
```bash Request headers
Authorization: Bearer mx_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
X-Organization-ID: org_xxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
```
All three MCP routes require the caller to be an **owner or admin** of the
organization. The `member` role cannot register or refresh MCP servers. See
[Roles & permissions](/security/roles-permissions).
The MCP server itself is authenticated separately, with the `headers` you supply
on registration. ModuleX sends those headers to the server on every connection —
for example a bearer token the server expects:
```json headers field
{
"Authorization": "Bearer your-mcp-server-token"
}
```
The server URL and headers can carry secrets (some hosted MCP servers encode a
per-user token in the URL path or query). ModuleX **encrypts** them at rest on
the credential and **masks** the URL in logs to scheme and host only — for
example `https://mcp.example.com`. The full URL is never logged.
## Register an MCP server
`POST /credentials/mcp-server` connects to the server, discovers its tools, and
creates one `mcp_server` credential.
### Request body
The MCP server endpoint URL, for example `https://mcp.example.com/mcp`.
ModuleX connects to this URL during discovery and again on every run.
Optional HTTP headers sent to the MCP server on every request, including auth —
for example `{"Authorization": "Bearer token"}`. Keys and values are strings.
Omit for an unauthenticated server.
Optional label for the credential. If omitted, ModuleX generates one from the
server's reported name and tool count, for example
`MCP Server - example (8 tools)`.
Whether to make this the default credential for the `mcp_server` integration in
this organization. A Tool node that omits `credential_id` cannot resolve an MCP
server, so for MCP this mostly affects which credential the app preselects.
There is no `transport_type` field on this request — the route always registers
the server with the `streamable_http` transport (see
[Transport and protocol](#transport-and-protocol)).
```bash cURL
curl https://api.modulex.dev/credentials/mcp-server \
-X POST \
-H "Authorization: Bearer mx_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Organization-ID: org_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"server_url": "https://mcp.example.com/mcp",
"headers": { "Authorization": "Bearer your-mcp-server-token" },
"display_name": "Example docs MCP",
"make_default": false
}'
```
```python Python
import asyncio
from modulex import AsyncModulex
client = AsyncModulex(
api_key="mx_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
organization_id="org_xxxxxxxxxxxxxxxxxxxxxxxx",
)
async def main():
credential = await client.credentials.create_mcp_server(
server_url="https://mcp.example.com/mcp",
headers={"Authorization": "Bearer your-mcp-server-token"},
display_name="Example docs MCP",
make_default=False,
)
print(credential.credential_id)
print(credential.credentials_metadata["tool_count"])
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from "modulex";
const client = new Modulex({
apiKey: "mx_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
organizationId: "org_xxxxxxxxxxxxxxxxxxxxxxxx",
});
const credential = await client.credentials.mcpServer({
serverUrl: "https://mcp.example.com/mcp",
headers: { Authorization: "Bearer your-mcp-server-token" },
displayName: "Example docs MCP",
makeDefault: false,
});
console.log(credential.credential_id);
```
### Response
A successful call returns `201`-style credential data shaped as
`MCPServerCredentialResponse`. This is a narrower shape than the standard
credential response — it omits `updated_at`, `integration_type`, `last_used_at`,
and `expires_at`.
The new credential's ID. Use it as `tool.credential_id` in a Tool node and as
the path parameter for refresh and list calls.
Always `mcp_server`.
The label, either the one you supplied or the generated default.
Always `custom` for MCP server credentials.
Whether this is the default `mcp_server` credential for the organization.
ISO 8601 creation timestamp.
The discovery metadata, including the discovered tools.
ISO 8601 timestamp of the first discovery.
ISO 8601 timestamp of the most recent discovery (equals `discovered_at` on
first create).
How many times discovery has been re-run; `0` on create.
`{name, version, protocol_version, url, transport_type}`. `version` is
`unknown` unless the server reports one; `protocol_version` is `2024-11-05`;
`transport_type` is `streamable_http`.
The discovered tools, each `{name, description, input_schema}` (see
[What a discovered tool looks like](#what-a-discovered-tool-looks-like)).
MCP resources. Currently always empty `[]`.
MCP prompts. Currently always empty `[]`.
The number of discovered tools.
```json Example response
{
"credential_id": "9f2a6b1c-4d3e-4a8f-9c10-2e7b5a1d8f33",
"integration_name": "mcp_server",
"display_name": "Example docs MCP",
"auth_type": "custom",
"is_default": false,
"created_at": "2026-06-21T10:14:00.000Z",
"credentials_metadata": {
"discovered_at": "2026-06-21T10:14:00.000Z",
"last_refreshed_at": "2026-06-21T10:14:00.000Z",
"refresh_count": 0,
"server_info": {
"name": "example-docs",
"version": "unknown",
"protocol_version": "2024-11-05",
"url": "https://mcp.example.com/mcp",
"transport_type": "streamable_http"
},
"tools": [
{
"name": "search_documents",
"description": "Full-text search across the docs corpus.",
"input_schema": {
"type": "object",
"properties": {
"query": { "type": "string" },
"limit": { "type": "integer" }
},
"required": ["query"]
}
}
],
"resources": [],
"prompts": [],
"tool_count": 1
}
}
```
## List discovered tools
`GET /credentials/{credential_id}/mcp-tools` returns the tools currently stored
on the credential. It reads the persisted `credentials_metadata.tools` — it does
**not** reconnect to the server (use [refresh](#refresh-tool-discovery) for that).
The MCP server credential's ID.
```bash cURL
curl https://api.modulex.dev/credentials/9f2a6b1c-4d3e-4a8f-9c10-2e7b5a1d8f33/mcp-tools \
-H "Authorization: Bearer mx_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Organization-ID: org_xxxxxxxxxxxxxxxxxxxxxxxx"
```
```python Python
tools = await client.credentials.mcp_tools(
"9f2a6b1c-4d3e-4a8f-9c10-2e7b5a1d8f33",
)
print(tools.total_count)
for tool in tools.tools:
print(tool["name"])
```
```javascript JavaScript
const tools = await client.credentials.mcpTools(
"9f2a6b1c-4d3e-4a8f-9c10-2e7b5a1d8f33",
);
console.log(tools.total_count);
```
### Response
The credential queried.
The discovered tool descriptors, each `{name, description, input_schema}`.
The number of tools returned.
## Refresh tool discovery
`POST /credentials/{credential_id}/refresh-discovery` reconnects to the server,
re-lists its tools, updates the stored `credentials_metadata`, and returns a
summary of what changed. Run it after the server adds or removes tools. It is
valid only for `mcp_server` credentials; any other credential returns `400`.
The MCP server credential to refresh.
This route takes **no request body** — the server URL, headers, and transport
are read from the stored credential.
```bash cURL
curl https://api.modulex.dev/credentials/9f2a6b1c-4d3e-4a8f-9c10-2e7b5a1d8f33/refresh-discovery \
-X POST \
-H "Authorization: Bearer mx_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Organization-ID: org_xxxxxxxxxxxxxxxxxxxxxxxx"
```
```python Python
result = await client.credentials.refresh_mcp_discovery(
"9f2a6b1c-4d3e-4a8f-9c10-2e7b5a1d8f33",
)
print(result.changes)
print(result.total_tools)
```
```javascript JavaScript
const result = await client.credentials.refreshDiscovery(
"9f2a6b1c-4d3e-4a8f-9c10-2e7b5a1d8f33",
);
console.log(result.changes);
```
### Response
The credential refreshed.
ISO 8601 timestamp of this refresh.
A diff against the previous tool set.
Names of tools newly present on the server.
Names of tools no longer present.
Tool count before the refresh.
Tool count after the refresh.
The tool count after the refresh.
Whether the refresh completed.
```json Example response
{
"credential_id": "9f2a6b1c-4d3e-4a8f-9c10-2e7b5a1d8f33",
"refreshed_at": "2026-06-21T11:02:13.000Z",
"changes": {
"added": ["summarize_document"],
"removed": [],
"total_before": 1,
"total_after": 2
},
"total_tools": 2,
"success": true
}
```
## Use an MCP tool in a workflow
A [Tool node](/workflow-builder/nodes/tool) calls an MCP tool the same way it
calls a catalog action, with three differences: `integration_name` is the literal
`mcp_server`, `credential_id` is **required** (the URL, headers, and transport
live on the credential, not the catalog), and `service_name` is the MCP tool's
name.
```json Tool node — MCP tool definition
{
"tool": {
"integration_name": "mcp_server",
"service_name": "search_documents",
"credential_id": "9f2a6b1c-4d3e-4a8f-9c10-2e7b5a1d8f33"
},
"input_mapping": {
"query": "{{intake_1.question}}",
"limit": 5
}
}
```
At run time ModuleX loads the credential, connects to the server, lists its
tools, selects the one matching `service_name`, and invokes it with the mapped
inputs. The output is parsed back into structured data, so you reference it like
any other node output. See the [Tool node](/workflow-builder/nodes/tool)
reference for `input_mapping`, parameter defaults and overrides, and the output
shape.
## Errors
These routes use the standard `{detail}` HTTPException envelope (a string or, for
the org rate limit, an object) — **not** the flat billing `DenialEnvelope`. The
MCP credential routes are CRUD-style and have **no per-call credit gate** (the
credit gate applies to `modulex_key` resolution at execution time, not to these
routes). For the complete error model, see
[Errors & status codes](/api-reference/errors).
| Status | When | Detail |
| --- | --- | --- |
| `400` | Connection or discovery failed; or refresh called on a non-`mcp_server` credential | `CredentialValidationError` message |
| `401` / `403` | Missing/invalid API key, or caller is not an owner/admin | auth dependency message |
| `404` | Credential not found in this organization (refresh / list) | `CredentialNotFoundError` message |
| `429` | Organization-class API rate limit (fail-open; includes `X-RateLimit-*` headers) | rate-limit object |
| `500` | Internal failure persisting the credential | `CredentialServiceError` message |
A connection or discovery failure surfaces as `400` with a
`Failed to connect to MCP server: ...` message. Verify the server URL is
reachable and that any auth header the server expects is present and correct
before retrying.
## SDK reference
Every operation maps to a method in both official SDKs.
| REST route | Python (`modulex-python`) | JavaScript (`modulex-js`) |
| --- | --- | --- |
| `POST /credentials/mcp-server` | `credentials.create_mcp_server(...)` | `credentials.mcpServer(...)` |
| `POST /credentials/{id}/refresh-discovery` | `credentials.refresh_mcp_discovery(id)` | `credentials.refreshDiscovery(id)` |
| `GET /credentials/{id}/mcp-tools` | `credentials.mcp_tools(id)` | `credentials.mcpTools(id)` |
Parity note: the JS `MCPServerCredentialResponse` mirrors the backend's narrower
MCP shape (it omits `updated_at`, `integration_type`, `last_used_at`, and
`expires_at` relative to a standard credential response). For the full
cross-language matrix, see the [SDK ⇄ API parity matrix](/sdks/parity).
## Limitations
`POST /credentials/mcp-server` always registers a server with the
`streamable_http` transport; the `sse` transport is not selectable through
the request body. (TBD: a public way to choose the transport.)
The tool list is captured at registration and persisted on the credential. A
`GET .../mcp-tools` call reads that snapshot; it does not reconnect. Run
[refresh](#refresh-tool-discovery) to pick up tools the server has added or
removed.
MCP `resources` and `prompts` are recorded as empty arrays; only `tools` are
discovered and usable today.
Registering, refreshing, and listing MCP servers require the owner or admin
role. The `member` role is retired and cannot perform these actions — see
[Roles & permissions](/security/roles-permissions).
For other documented gaps, see [Known limitations](/reference/known-limitations).
## Related
Wire an MCP tool into a workflow with `integration_name: mcp_server`.
The code path: author a package integration with the `@tool` contract.
How ModuleX stores and resolves credentials, including `custom` types.
Create, scope, and rotate credentials in the app and via API.
---
# Manifest & schema contract
URL: https://docs.modulex.dev/integrations/building/manifest-schema
The complete Pydantic contract every ModuleX integration manifest must satisfy — IntegrationManifest, ActionDefinition, ParameterDef, the six auth schema variants, EnvVar, and TestEndpoint.
Every ModuleX integration declares itself through a single Pydantic contract. Your integration's `manifest.py` constructs one `IntegrationManifest` instance, and the ModuleX runtime imports it through the `modulex.tools` entry-point group to drive credential setup, validation, and tool discovery. This page is the exhaustive field reference for that contract.
The contract is defined in `schema.py` in the `modulex-integrations` package. Once you understand the manifest, read the [@tool function contract](/integrations/building/tool-contract) for the executable side, and [Build an integration](/integrations/building/overview) for the end-to-end workflow.
Every model in the schema sets `extra="forbid"`. Any field name that is not part of the contract — a typo, or a legacy field the new schema dropped — fails at **import time, not at runtime**. There is no silent acceptance of unknown keys.
## How the contract is consumed
The runtime discovers integrations through the `modulex.tools` Python entry-point group. Each entry point names a `modulex_integrations.tools.` package that exposes exactly two public names:
- `manifest` — one `IntegrationManifest` instance.
- `TOOLS` — a tuple of LangChain `StructuredTool` objects, one per action.
The backend reads both, then converts the manifest plus the `@tool` tuple into the action shape it serves to the model and the app. Two consequences shape the entire schema:
1. **`auth_schemas` is a discriminated union** keyed on `auth_type`. A single integration can expose more than one credential method — GitHub ships OAuth2 and a personal access token side by side.
2. **Action output schemas are intentionally absent from the manifest.** The return shape of every action is derived from its `@tool` function's return-type annotation (defined in `outputs.py`) via `Model.model_json_schema()` at startup — not declared in the manifest. See [Output models are not in the manifest](#output-models-are-not-in-the-manifest).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4180 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** Diagram of how a manifest flows from package to runtime.
**[IMAGE_DETAILS]:** Show a single integration package box containing `manifest.py` (produces `manifest`), `tools.py` (produces `TOOLS`), and `outputs.py` (typed return models). An arrow labeled `modulex.tools entry-point group` points to the ModuleX runtime, which reads `manifest` and `TOOLS`, derives each action's output schema from the `@tool` return annotation, and emits the credential UI, validation, and tool discovery surfaces. Landscape, light theme, no UI chrome, annotate the `extra="forbid"` import-time validation step.
## `IntegrationManifest`
The top-level model your `manifest.py` produces. Every other model on this page is reachable from here.
The only accepted value is `"tool"`. It distinguishes a tool integration from the LLM and knowledge providers, which live inside the ModuleX backend rather than in this package.
The integration's identifier. Must match the pattern `^[a-z][a-z0-9_]*$` — lowercase, snake_case, starting with a letter. It must equal the entry-point key and the package directory name (for example `github`, `google_ads`).
The human-readable label shown in the app, for example `"GitHub"`.
A one-line description of what the integration does.
The per-integration manifest version. This is **not** the `modulex-integrations` package version.
The integration author.
The logo reference. The convention is `"modulex:-themed"`, for example `"modulex:github-themed"`.
The provider's homepage URL.
Free-form category strings used to group the integration in the catalog, for example `["Developer Tools & Infrastructure", "version-control", "productivity"]`.
The list of callable actions the integration exposes. See [`ActionDefinition`](#actiondefinition).
The credential methods the integration supports, as a discriminated union on `auth_type`. See [Auth schemas](#auth-schemas-the-discriminated-union). A single integration may list more than one variant.
There is **no** `output_schema`, `docs_url`, `features`, `rate_limits`, `pricing`, or `metadata` field on `IntegrationManifest`. The earlier `_integration.json` format carried several informational fields the Pydantic schema deliberately drops; because `extra="forbid"` rejects them, they must be removed when you migrate a manifest and kept only in the integration's README.
## `ActionDefinition`
One callable action exposed by the integration. The return shape is **not** declared here — it is derived from the matching `@tool` function's return annotation in `tools.py` and `outputs.py`.
The action name. Must match the pattern `^[a-z][a-z0-9_]*$` and must equal a `@tool` function name in the package's `TOOLS` tuple.
A one-line description of what the action does.
The action's parameters, keyed by parameter name. See [`ParameterDef`](#parameterdef).
### `ParameterDef`
A single action parameter.
The parameter type. One of `"string"`, `"integer"`, `"number"`, `"boolean"`, `"array"`, or `"object"`.
A one-line description of the parameter.
The default value when the parameter is omitted.
Whether the parameter must be supplied. Defaults to `false`.
Note the contrast with [`EnvVar.required`](#envvar), which defaults to `true`.
Here is a single action with two parameters:
```python actions example
ActionDefinition(
name="list_repositories",
description="List repositories for the authenticated user or organization",
parameters={
"visibility": ParameterDef(
type="string",
description="Filter by visibility: all, public, private",
default="all",
),
"per_page": ParameterDef(
type="integer",
description="Results per page",
default=30,
),
},
)
```
The manifest `parameters` are **not** the authoritative list of an action's callable arguments — the `@tool` function's `args_schema` is. Several shipped actions accept arguments (for example GitHub `create_issue` accepts `assignees`) that the function forwards to the upstream API but the manifest does not list. Treat manifest `parameters` as descriptive catalog metadata; the [@tool function contract](/integrations/building/tool-contract) defines what the action actually accepts.
## Auth schemas: the discriminated union
`AuthSchema` is a Pydantic discriminated union over six variant classes, keyed on the `auth_type` literal. List one or more variants on `IntegrationManifest.auth_schemas`. GitHub, for example, ships `OAuth2AuthSchema` plus `BearerTokenAuthSchema`; Exa ships `ApiKeyAuthSchema` plus `ModulexKeyAuthSchema`.
### Shared base fields
Every variant inherits these fields from `_AuthSchemaBase`:
The credential method's label in the app, for example `"OAuth2 Authentication"` or `"Personal Access Token"`.
A one-line description of the credential method.
An ordered list of human setup steps shown in the credential UI.
The secrets and settings the operator must provide for this method. See [`EnvVar`](#envvar).
The HTTP call the runtime makes to validate a configured credential. **Optional** — some `modulex_key` "public API" integrations (for example `instacart`, `hackernews`) have no credential to validate and ship no test endpoint; the runtime skips credential testing in that case. See [`TestEndpoint`](#testendpoint).
### The six variants
Each variant adds only its `auth_type` discriminator. `OAuth2AuthSchema` additionally requires an `oauth_config`.
| Class | `auth_type` | Extra field | Used by (verified samples) |
| --- | --- | --- | --- |
| `OAuth2AuthSchema` | `"oauth2"` | `oauth_config: OAuthConfig` | `github`, `google_calendar`, `netlify` |
| `BearerTokenAuthSchema` | `"bearer_token"` | — | `github` (personal access token) |
| `ApiKeyAuthSchema` | `"api_key"` | — | `exa`, `convertapi`, `hunter`, `freshdesk` |
| `ModulexKeyAuthSchema` | `"modulex_key"` | — | `exa` (managed key), `hackernews`, `instacart`, `firecrawl`, `jina_ai` |
| `CustomAuthSchema` | `"custom"` | — | `postgresql`, `woocommerce`, `coinbase`, `mintlify` |
| `InternalAuthSchema` | `"internal"` | — | None in the catalog — reserved variant |
`InternalAuthSchema` is **defined but unused.** No shipped integration instantiates it. It remains a valid wire `auth_type` on the ModuleX side (the backend credential constraint accepts `'internal'`), so treat it as a reserved or forward-looking variant rather than an option to author against today.
Separately, the backend credential constraint accepts a **seventh** value, the legacy `'bearer'`, which has no corresponding schema variant. New integrations must emit only the six variants above; `'bearer'` exists only as a legacy database value.
### `OAuthConfig`
Required on `OAuth2AuthSchema` only. Carries the OAuth 2.0 authorize and token endpoints plus per-provider flags.
The provider's authorization URL.
The provider's token-exchange URL.
The OAuth scopes to request, for example `["repo", "user", "read:org", "workflow"]`.
How client credentials are presented at the token exchange — in the request body, or as HTTP Basic auth.
An extra authorize-URL parameter for providers that require an explicit opt-in to refresh tokens. Google needs `"offline"` to issue a `refresh_token`.
An extra authorize-URL parameter. Setting `"consent"` forces the provider to re-issue a refresh token on every reconnect rather than only on the user's first authorization.
Whether the provider supports PKCE (RFC 7636) on the authorization-code flow. Defaults to `true`. Set it to `false` for providers that reject an unexpected `code_verifier` with `invalid_grant` — Netlify is the shipped example. The ModuleX runtime reads this flag from the manifest when it builds the authorization URL (`use_pkce=oauth_config.get("use_pkce", True)`), so a manifest opt-out is honored end to end.
A source-research note flagged `use_pkce` as possibly not yet honored by the runtime ("the runtime currently hardcodes PKCE on"). Verified against the current backend: `credentials.py` reads `oauth_config.get("use_pkce", True)` when generating the authorization URL, so the manifest flag **is** honored. This page reflects the current behavior.
Here is a complete OAuth2 auth schema:
```python OAuth2AuthSchema example
OAuth2AuthSchema(
display_name="OAuth2 Authentication",
description="Connect using GitHub OAuth (recommended for most use cases)",
setup_environment_variables=[
EnvVar(
name="GITHUB_OAUTH2_CLIENT_ID",
display_name="Client ID",
description="GitHub OAuth App Client ID",
required=True,
sensitive=False,
only_for_custom=True,
sample_format="Iv1.xxxxxxxxxxxxxxxx",
about_url="https://github.com/settings/applications/new",
),
# ... CLIENT_SECRET with sensitive=True ...
],
oauth_config=OAuthConfig(
auth_url="https://github.com/login/oauth/authorize",
token_url="https://github.com/login/oauth/access_token",
scopes=["repo", "user", "read:org", "workflow"],
token_auth_method="body",
),
test_endpoint=TestEndpoint(
url="https://api.github.com/user",
method="GET",
headers={
"Authorization": "Bearer {access_token}",
"Accept": "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28",
},
success_indicators=SuccessIndicators(
status_codes=[200],
response_fields=["login", "id"],
),
cost_level="free",
description="Validates the OAuth token by fetching authenticated user info",
),
)
```
For how ModuleX stores and resolves the resulting credentials, see [Credentials & OAuth2](/concepts/credentials-oauth) and [Authentication & credentials](/integrations/authentication).
## `EnvVar`
A configurable secret or setting the operator must provide, listed under an auth schema's `setup_environment_variables`.
The environment-variable-style key, for example `GITHUB_OAUTH2_CLIENT_ID`.
The label shown in the credential UI.
A one-line description of the value.
Whether the value must be supplied. Defaults to `true` — the opposite of [`ParameterDef.required`](#parameterdef), which defaults to `false`.
Whether the value is a secret. When `true`, it is masked in the UI (use it for client secrets and tokens).
Whether the value is a server-level secret. When `true`, the managed ModuleX app resolves it from the server environment, while a bring-your-own-app operator supplies their own (for example a GitHub OAuth client ID and secret, or a Google Ads `developer_token`).
Whether the runtime guarantees this value is present in the credential's `auth_data` at action-execution time, so a `tools.py` function can read it. The value is read by its normalized (prefix-stripped, lowercased) key.
When `false` (the default), the `EnvVar` is used only for OAuth provider configuration and the credential test endpoint, never for action calls.
A placeholder hint shown in the UI, for example `"ghp_xxxx..."`.
A link to where the operator obtains the value.
### `only_for_custom` × `inject_into_auth_data`
These two flags together determine where a value comes from and whether it reaches your `tools.py` function:
- **`inject_into_auth_data=false`** (default) — the value is OAuth or test-endpoint only. It never reaches `tools.py`.
- **`inject_into_auth_data=true` + `only_for_custom=false`** — per-credential **user input**. The runtime persists the user-entered value into `auth_data` at credential creation (for example a Google Merchant Center `merchant_id`).
- **`inject_into_auth_data=true` + `only_for_custom=true`** — a **server-level secret**. The managed app injects it from the server environment at credential-resolution time, while a bring-your-own-app operator supplies their own (for example a Google Ads `developer_token`).
## `TestEndpoint`
The HTTP call the runtime makes to validate a configured credential. URL, header, body, and query-parameter values may contain placeholders such as `{access_token}`, `{token}`, `{api_key}`, `{bearer_token}`, or any `auth_data` or `EnvVar` key, which the runtime substitutes with the resolved credential value before making the call.
The endpoint URL. May embed query placeholders, for example ConvertAPI's `?Secret={api_key}`.
The HTTP method for the validation call.
Request headers, for example `{"Authorization": "Bearer {access_token}"}`.
The URL query string, used by integrations that pass their credential as a query parameter.
A JSON payload sent on non-GET methods, for example Exa's `POST /search` validation call.
An optional declarative directive for HTTP Basic auth synthesis. When set, the runtime builds the `Authorization: Basic ` header itself and ignores any `Authorization` entry in `headers`. See [`BasicAuthSpec`](#basicauthspec).
How the runtime decides the validation call succeeded. See [`SuccessIndicators`](#successindicators).
A free-form hint about the cost of the validation call. Observed values include `"free"` and `"minimal"`; the schema does not constrain the set.
A one-line description of what the validation call checks.
### `SuccessIndicators`
How to tell a credential test endpoint succeeded.
The HTTP status codes treated as success, for example `[200]`.
Keys expected to be present in the response body, for example `["login", "id"]`.
### `BasicAuthSpec`
Declarative Basic auth for test endpoints where the Base64 cannot be precomputed because one or both halves are user secrets. The runtime resolves each placeholder against `auth_data`; if a placeholder name is **not** a key in `auth_data`, it is treated as a **literal** string (Mailgun, for example, uses `username_placeholder="api"`).
The auth synthesis type. The only value is `"basic"`.
The placeholder or literal used as the Basic auth username.
The placeholder or literal used as the Basic auth password.
Here is a Basic-auth test endpoint:
```python TestEndpoint with BasicAuthSpec
TestEndpoint(
url="https://api.twilio.com/2010-04-01/Accounts/{TWILIO_ACCOUNT_SID}.json",
method="GET",
auth=BasicAuthSpec(
username_placeholder="TWILIO_ACCOUNT_SID",
password_placeholder="TWILIO_AUTH_TOKEN",
),
success_indicators=SuccessIndicators(
status_codes=[200],
response_fields=["sid"],
),
cost_level="free",
description="Validates the Account SID and Auth Token by fetching the account.",
)
```
## Output models are not in the manifest
Neither `ActionDefinition` nor `IntegrationManifest` carries an output schema. The return shape of every action is derived at backend startup from its `@tool` function's return-type annotation: the runtime resolves the annotation, and if the return type has a `model_json_schema()` method, it calls it to produce the model-facing output schema.
This is why your action's typed Pydantic return model lives in `outputs.py`, and why the `@serialize_pydantic_return` wrapper must preserve the annotation while coercing the runtime value to a dict. Reading a manifest alone will never reveal an action's output shape — see the [@tool function contract](/integrations/building/tool-contract) for the full output-model and decorator rules.
## Full manifest example
This abridged GitHub manifest shows the whole contract assembled: two auth schemas (OAuth2 and a personal access token) and a set of actions.
```python manifest.py
from modulex_integrations.schema import (
ActionDefinition,
BearerTokenAuthSchema,
EnvVar,
IntegrationManifest,
OAuth2AuthSchema,
OAuthConfig,
ParameterDef,
SuccessIndicators,
TestEndpoint,
)
manifest = IntegrationManifest(
name="github",
display_name="GitHub",
description="GitHub repository and code management platform",
version="1.0.0",
author="ModuleX",
logo="modulex:github-themed",
app_url="https://github.com",
categories=["Developer Tools & Infrastructure", "version-control", "productivity"],
actions=[
ActionDefinition(
name="create_repository",
description="Create a new repository",
parameters={
"name": ParameterDef(
type="string", description="Repository name", required=True
),
"description": ParameterDef(
type="string", description="Repository description"
),
"private": ParameterDef(
type="boolean",
description="Whether the repository is private",
default=False,
),
},
),
# ... more actions ...
],
auth_schemas=[
OAuth2AuthSchema(
display_name="OAuth2 Authentication",
description="Connect using GitHub OAuth (recommended for most use cases)",
setup_environment_variables=[
EnvVar(
name="GITHUB_OAUTH2_CLIENT_ID",
display_name="Client ID",
description="GitHub OAuth App Client ID",
required=True,
sensitive=False,
only_for_custom=True,
sample_format="Iv1.xxxxxxxxxxxxxxxx",
about_url="https://github.com/settings/applications/new",
),
# ... CLIENT_SECRET with sensitive=True ...
],
oauth_config=OAuthConfig(
auth_url="https://github.com/login/oauth/authorize",
token_url="https://github.com/login/oauth/access_token",
scopes=["repo", "user", "read:org", "workflow"],
token_auth_method="body",
),
test_endpoint=TestEndpoint(
url="https://api.github.com/user",
method="GET",
headers={
"Authorization": "Bearer {access_token}",
"Accept": "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28",
},
success_indicators=SuccessIndicators(
status_codes=[200], response_fields=["login", "id"]
),
cost_level="free",
description="Validates OAuth token by fetching authenticated user info",
),
),
BearerTokenAuthSchema(
display_name="Personal Access Token",
description="Use your GitHub Personal Access Token (Classic or Fine-grained)",
setup_instructions=[
"Go to GitHub Settings then Developer settings then Personal access tokens",
"Generate a token with the repo and user scopes",
"Paste the token below",
],
setup_environment_variables=[
EnvVar(
name="GITHUB_PERSONAL_TOKEN",
display_name="Personal Access Token",
description="GitHub Personal Access Token",
required=True,
sensitive=True,
),
],
test_endpoint=TestEndpoint(
url="https://api.github.com/user",
headers={"Authorization": "Bearer {bearer_token}"},
success_indicators=SuccessIndicators(
status_codes=[200], response_fields=["login", "id"]
),
),
),
],
)
```
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4181 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The credential setup UI rendered from a manifest's auth schemas.
**[SCREENSHOT_DETAILS]:** Capture the in-app "Connect integration" panel for an integration that ships multiple auth schemas (GitHub is ideal — OAuth2 plus Personal Access Token). Show the method selector reflecting the two `auth_schemas`, the `EnvVar` fields rendered with their `display_name` labels, a masked `sensitive=True` field, and the `setup_instructions` list. Light theme, desktop width, no real secret values visible.
## Validation rules to remember
Every model sets `extra="forbid"`. A misspelled field name or a leftover legacy field stops the package from importing — you find out immediately, not when a credential is created.
Both `IntegrationManifest.name` and `ActionDefinition.name` must match `^[a-z][a-z0-9_]*$`. The integration name must also equal the entry-point key and the package directory name; each action name must equal a `@tool` function name in `TOOLS`.
`ParameterDef.required` defaults to `false`; `EnvVar.required` defaults to `true`. Set them explicitly when the default is not what you want.
A `modulex_key` "public API" integration with no credential to validate can omit `test_endpoint` entirely; the runtime then skips credential testing.
Manifest `parameters` are catalog metadata. The `@tool` function's `args_schema` is the authoritative list of arguments an action accepts, and output shapes come from the function's return annotation, not the manifest.
## Next steps
The decorator order, auth parameter patterns, and Pydantic output models that pair with this manifest.
The end-to-end workflow for authoring and registering your own integration.
How the six auth schema variants map onto credential setup and OAuth2 (PKCE).
Canonical definitions for every manifest term used on this page.
---
# Build an integration
URL: https://docs.modulex.dev/integrations/building/overview
Author your own ModuleX integration end to end: the per-integration directory layout, the manifest, the @tool function contract, entry-point registration in the modulex.tools group, and how to test it locally before the runtime loads it.
An integration is a connector to an external service that exposes one or more **tools** — callable actions an [LLM node](/workflow-builder/nodes/llm), an [Agent node](/workflow-builder/nodes/agent), the [AI Composer](/concepts/ai-composer), and the [Assistant](/assistant/overview) can invoke. Every integration ships from the public `modulex-integrations` package as a Python package, and the ModuleX runtime discovers it through the `modulex.tools` entry-point group and loads it at startup.
This page is the end-to-end author's guide: the directory the runtime expects, the manifest it reads, the `@tool` function contract it executes, how you register your integration so the runtime can find it, and how to test it locally. Two companion pages go deeper on the contracts referenced throughout: the [manifest and schema contract](/integrations/building/manifest-schema) (every field, type, default, and the six auth schema variants) and the [@tool function contract](/integrations/building/tool-contract) (decorator order, auth-parameter conventions, output models, and error patterns). If instead of authoring a package you want to plug in an external server, see [custom MCP servers](/integrations/building/custom-mcp).
The `modulex-integrations` package targets **Python 3.12+** and is built with Hatchling + hatch-vcs (the version is derived from git tags; there is no central version file). Its three always-installed core dependencies are `pydantic>=2.5.0`, `httpx>=0.25.0`, and `langchain-core>=0.3.0`. Everything a specific tool needs beyond those is per-tool.
## Before you start
Choose a lowercase, snake-case integration name that matches the pattern `^[a-z][a-z0-9_]*$` — for example `github`, `google_ads`, `mongodb_atlas`. This one string is your directory name, your entry-point key, your manifest `name`, and the credential/catalog key the runtime uses. They must all be identical.
The `dev` extras group pulls in `pytest`, `pytest-asyncio`, `pytest-httpx`, `ruff`, and `mypy`, plus a hand-maintained mirror of several vendor SDKs so type-checking can import them.
```bash
git clone https://github.com/ModuleXAI/modulex-integrations.git
cd modulex-integrations
pip install -e ".[dev]"
pytest
```
The fastest path is to copy a folder under `src/modulex_integrations/tools/` (for example `github` for a token-auth REST API, or `exa` for an API-key service), then edit the manifest, tools, outputs, and tests for your service. Every integration ships the identical file set, so reviews are mechanical.
## Anatomy of an integration
Every integration lives at `src/modulex_integrations/tools//` and ships the same fixed set of files. The contract is enforced by pydantic types in `schema.py` with `extra="forbid"` everywhere — a typo in a manifest fails at **import time**, not at runtime.
```text The per-integration directory layout
src/modulex_integrations/tools//
├── __init__.py # re-exports `manifest` + `TOOLS`
├── manifest.py # IntegrationManifest instance bound to the name `manifest`
├── tools.py # LangChain @tool functions (one per action)
├── outputs.py # pydantic response models (output schema derived from these)
├── dependencies.toml # per-integration runtime deps
├── README.md # 5-section strict template
└── tests/
├── __init__.py # empty
└── test_.py # ≥1 happy-path test per @tool
```
Builds one `IntegrationManifest` instance named `manifest`: metadata, `actions`, and `auth_schemas`. The single source of truth for the integration's identity and how it authenticates.
The per-action `args_schema` input models and the `@tool` functions, plus an auth-header helper. The `@tool` function names must match the manifest `actions`.
Typed pydantic output models, one per action, used as `@tool` return annotations. The runtime derives each action's output schema from these.
The public surface the runtime imports: it re-exports `manifest` and a `TOOLS` tuple of the `@tool` objects.
A `dependencies = [...]` list of the vendor SDKs this tool needs (often empty when only `httpx` is used).
A five-section human doc (title, Authentication, Tools, Limits & Quotas, Maintainer). CI enforces the section list.
### The two symbols the runtime reads
The runtime imports your integration's `__init__.py` and reads exactly two names. Nothing else in the module is part of the runtime contract.
An `IntegrationManifest` instance (re-exported from `manifest.py`) describing the integration's metadata, actions, and auth schemas. See the [manifest and schema contract](/integrations/building/manifest-schema) for every field.
A **tuple** of LangChain `StructuredTool` objects, one per action — the `@tool`-decorated functions from `tools.py`. Both the runtime and the docs export script read `getattr(module, "TOOLS", ())`, so the attribute must be a tuple named exactly `TOOLS`.
A minimal `__init__.py` re-exports both symbols:
```python src/modulex_integrations/tools//__init__.py
""" integration — discovered by the modulex runtime via the
``modulex.tools`` entry point declared in the root ``pyproject.toml``.
The runtime imports this module, then reads:
- ``manifest`` — an IntegrationManifest describing metadata, actions, and auth schemas.
- ``TOOLS`` — a tuple of LangChain StructuredTool objects, one per action.
"""
from modulex_integrations.tools..manifest import manifest
from modulex_integrations.tools..tools import (
create_thing,
list_things,
)
TOOLS = (
list_things,
create_thing,
)
__all__ = ["TOOLS", "create_thing", "list_things", "manifest"]
```
## Step 1 — Write the manifest
`manifest.py` builds exactly one `IntegrationManifest` instance bound to the module-level name `manifest`. The model rejects unknown fields (`extra="forbid"`), so import will fail if you add a field that is not in the schema. There is **no** `output_schema`, `docs_url`, `features`, `rate_limits`, `pricing`, or `metadata` field — those belong in the README, not the manifest.
### `IntegrationManifest` fields
Always `tool` — the only allowed value. (LLM and knowledge providers are not authored here; they stay in the `modulex` backend.)
The integration name. Must match the pattern `^[a-z][a-z0-9_]*$` and be identical to the directory name and the entry-point key (for example `github`).
The human-facing label shown in the catalog and UI (for example `GitHub`).
A one-line description of what the integration does.
The per-integration manifest version — not the package version.
The author/maintainer name.
Logo reference. Convention is `modulex:-themed` (for example `modulex:github-themed`).
The provider's homepage URL.
Free-form category strings used to group the integration in the catalog (for example `["Developer Tools & Infrastructure", "version-control"]`).
One `ActionDefinition` per callable action. Each action's `name` must match a `@tool` function name in `TOOLS`.
A list from the discriminated union of the six auth variants (keyed on `auth_type`). An integration may expose more than one — GitHub ships OAuth2 plus a personal-access-token bearer schema. See the [six auth schema variants](/integrations/building/manifest-schema).
Each action is an `ActionDefinition`. The action's output shape is **not** declared here — it is derived from the matching `@tool` function's return annotation at backend startup, so the manifest never carries an `output_schema`.
The action name. Must match `^[a-z][a-z0-9_]*$` and equal a `@tool` function name in `TOOLS`.
A one-line description of the action.
A mapping of parameter name to `ParameterDef`.
Each `ParameterDef` describes one parameter:
One of `string`, `integer`, `number`, `boolean`, `array`, or `object`.
A one-line description of the parameter.
The default value when the parameter is omitted.
Whether the parameter must be supplied. Note this defaults to `false` — the opposite of `EnvVar.required`, which defaults to `true`.
The manifest `parameters` are **not** the authoritative list of what a tool accepts — the `@tool` function's `args_schema` is. In several shipped integrations a parameter exists on the `args_schema` (and reaches the upstream API) but is omitted from the manifest. Keep both in sync; the `args_schema` is the callable surface of truth.
A trimmed manifest for a token-auth REST integration looks like this:
```python src/modulex_integrations/tools//manifest.py
from modulex_integrations.schema import (
ActionDefinition,
BearerTokenAuthSchema,
EnvVar,
IntegrationManifest,
ParameterDef,
SuccessIndicators,
TestEndpoint,
)
manifest = IntegrationManifest(
name="acme",
display_name="Acme",
description="Acme task and project management",
version="1.0.0",
author="ModuleX",
logo="modulex:acme-themed",
app_url="https://acme.example.com",
categories=["Productivity"],
actions=[
ActionDefinition(
name="list_tasks",
description="List tasks in a project",
parameters={
"project_id": ParameterDef(type="string", description="Project id", required=True),
"limit": ParameterDef(type="integer", description="Max tasks to return", default=30),
},
),
],
auth_schemas=[
BearerTokenAuthSchema(
display_name="Personal Access Token",
description="Use your Acme API token",
setup_environment_variables=[
EnvVar(
name="ACME_TOKEN",
display_name="API Token",
description="Acme personal access token",
sensitive=True,
sample_format="acme_xxxxxxxx",
about_url="https://acme.example.com/settings/tokens",
),
],
test_endpoint=TestEndpoint(
url="https://api.acme.example.com/me",
method="GET",
headers={"Authorization": "Bearer {token}"},
success_indicators=SuccessIndicators(status_codes=[200], response_fields=["id"]),
cost_level="free",
),
),
],
)
```
For the full set of auth variants (`oauth2`, `bearer_token`, `api_key`, `modulex_key`, `custom`, `internal`), the `OAuthConfig`, `EnvVar`, `TestEndpoint`, `SuccessIndicators`, and `BasicAuthSpec` fields, and the `only_for_custom` versus `inject_into_auth_data` behavior, see the [manifest and schema contract](/integrations/building/manifest-schema).
## Step 2 — Write the `@tool` functions
`tools.py` holds one `async def` per action, each carrying a paired pydantic `args_schema` input model and a typed pydantic return annotation from `outputs.py`. Every function uses the same mandatory two-decorator stack.
The decorator order is non-negotiable: `@tool` is the **outer** decorator (applied last, closest to the call site) and `@serialize_pydantic_return` is the **inner** decorator. Reverse them and `@tool` receives the typed pydantic-returning function, the dict coercion never fires, and the runtime's `json.dumps()` boundary raises `TypeError: Object of type ... is not JSON serializable`.
```python src/modulex_integrations/tools//tools.py
from __future__ import annotations
from typing import Any
import httpx
from langchain_core.tools import tool
from pydantic import BaseModel, Field
from modulex_integrations import serialize_pydantic_return
from modulex_integrations.tools.acme.outputs import ListTasksOutput
class ListTasksInput(BaseModel):
auth_type: str = Field(description="Authentication type (oauth2, bearer_token)")
auth_data: dict[str, Any] = Field(description="Authentication data containing tokens")
project_id: str = Field(description="Project id")
limit: int = Field(default=30, description="Max tasks to return")
@tool(args_schema=ListTasksInput) # OUTER — applied last, closest to the call site
@serialize_pydantic_return # INNER — wraps the raw function
async def list_tasks(
auth_type: str,
auth_data: dict[str, Any],
project_id: str,
limit: int = 30,
) -> ListTasksOutput: # return annotation = the output model
"""List tasks in a project."""
headers = _get_auth_headers(auth_type, auth_data)
async with httpx.AsyncClient() as client:
response = await client.get(
f"https://api.acme.example.com/projects/{project_id}/tasks",
headers=headers,
params={"limit": limit},
)
response.raise_for_status()
data = response.json()
return ListTasksOutput(success=True, tasks=data.get("tasks", []))
```
Use `from __future__ import annotations` at the top of both `tools.py` and `outputs.py`. The backend reads each `@tool`'s return annotation via `typing.get_type_hints(...)` (not raw `__annotations__`) precisely to resolve these stringified PEP 563 annotations into the real pydantic class.
### Auth parameter conventions
The runtime injects credentials at call time and strips the credential fields from the schema the model sees, so the LLM never reads tokens. There are two conventions; pick the one that matches your auth schemas.
For `oauth2` and `bearer_token` schemas, the first two parameters are `auth_type: str` and `auth_data: dict[str, Any]`. A module-level helper builds the provider headers, branching on `auth_type`:
```python
def _get_auth_headers(auth_type: str, auth_data: dict[str, Any]) -> dict[str, str]:
headers = {"Accept": "application/json"}
if auth_type == "oauth2":
token = auth_data.get("access_token")
if token:
headers["Authorization"] = f"Bearer {token}"
elif auth_type == "bearer_token":
token = auth_data.get("token")
if token:
headers["Authorization"] = f"Bearer {token}"
return headers
```
For `api_key` and `modulex_key` schemas, take the credential parameter directly — for example `api_key: str` as the second parameter — instead of the `auth_type`/`auth_data` pair. The runtime auto-fills any function parameter whose name matches a key in the resolved credential (`api_key`, `token`, `access_token`). Add a non-empty check before any HTTP call:
```python
if not api_key or not api_key.strip():
return SearchOutput(success=False, error="API key is empty.")
headers = {"x-api-key": api_key}
```
### Output models
`outputs.py` defines one typed pydantic model per action. Each model subclasses a shared base with `model_config = ConfigDict(extra="forbid")`. The only field guaranteed across every integration is `success: bool`; an `error: str | None` field exists only on integrations whose tools return a failure payload rather than raising.
```python src/modulex_integrations/tools//outputs.py
from __future__ import annotations
from pydantic import BaseModel, ConfigDict, Field
class _Base(BaseModel):
model_config = ConfigDict(extra="forbid")
class TaskSummary(_Base):
id: str | None = None
title: str | None = None
status: str | None = None
class ListTasksOutput(_Base):
success: bool # required on every output model
tasks: list[TaskSummary] = Field(default_factory=list)
error: str | None = None # present only on inline-error integrations
```
The backend derives each action's LLM-facing output schema by calling `model_json_schema()` on the resolved return type at startup — which is why the return annotation must stay the pydantic class even though `@serialize_pydantic_return` coerces the runtime value to a dict.
### Choose one error pattern
Pick the pattern that fits how your upstream service signals failure and apply it consistently across the integration.
Call `response.raise_for_status()` after each request and only ever construct `success=True` models; HTTP errors propagate as exceptions. Output models have no `error` field. Use this when the upstream API returns standard HTTP error status codes.
The upstream returns HTTP 200 with a body like `{"ok": false, "error": "..."}`. Read the JSON, check the flag, and on failure return the output model with `success=False` and `error` set; on success leave `error` as `None`. Do not call `raise_for_status()` — inspect the body instead.
Wrap every call in `try/except` so non-2xx responses, timeouts, and unexpected exceptions all surface as `success=False` with `error` set, never raising. Pre-validate the credential and set explicit per-endpoint timeouts. Use this when you want the tool to always return a structured result.
For the fully annotated end-to-end examples (GitHub `create_issue`, Slack, Exa), the exact `serialize_pydantic_return` behavior, and how the annotation becomes the output schema, see the [@tool function contract](/integrations/building/tool-contract).
## Step 3 — Register the entry point
The ModuleX runtime discovers integrations through the Python **`modulex.tools` entry-point group**, not by scanning the filesystem. Add one line for your integration to the root `pyproject.toml`. The key is your integration name; the value is the `` **package** path (not the `.tools` module — the runtime appends `.tools` itself when it needs the tool module).
```toml pyproject.toml
[project.entry-points."modulex.tools"]
github = "modulex_integrations.tools.github"
slack = "modulex_integrations.tools.slack"
acme = "modulex_integrations.tools.acme"
```
After installing or upgrading the package, the runtime enumerates `entry_points(group="modulex.tools")`, imports each module, reads its `manifest` and `TOOLS`, converts them into the legacy action-dict shape it expects, and caches the result for the process lifetime. Restart the worker to pick up a freshly installed package version.
The docs/CI export script (`scripts/export_manifests.py`) uses a separate discovery mechanism: it **walks the filesystem** for `tools/*/manifest.py` and uses the entry-point table only as a cross-check. So a tool can exist on disk and export to the docs catalog even before its entry point is registered — but the **runtime will not load it** until the entry-point line is present. Always add the entry-point line.
### Declare runtime dependencies
List any vendor SDKs your tool imports in its `dependencies.toml`. Leave it as an empty list when the tool only uses `httpx` (already a core dependency).
```toml src/modulex_integrations/tools//dependencies.toml
dependencies = ["acme-sdk>=2.0.0"]
```
Do not rely on `pip install` extras to pull these in today. The `all` extra resolves to an empty list and there are **no** per-tool extras groups (`[github]`, `[slack]`, and the like are not defined), because the script that assembles `dependencies.toml` files into installable extras does not yet exist. Installing `modulex-integrations[all]` or `modulex-integrations[acme]` installs only the core package — pip will warn about the unknown extra. Until the assemble step lands, install `modulex-integrations` and then install each tool's SDKs manually per its `dependencies.toml`. See [installing integrations](/integrations/install).
## Step 4 — Write the README
Every integration's `README.md` follows the same five-section template, in order. CI enforces the section list, and the export script splits the README into the prose that keeps each generated catalog page from being thin content.
The display name as an H1, plus a one-to-two sentence summary naming the upstream API and its base URL.
One subsection per auth method: the environment variables, scopes, and token/authorize URLs.
A markdown table of `name | description | required params`, plus the note that the runtime injects the auth parameters.
Rate limits and the integration's error-model behavior (raise versus inline `ok:false` versus try/except).
Your GitHub handle, or "ModuleX core team".
## Step 5 — Test it locally
Each integration ships at least one happy-path test per `@tool`, plus a manifest sanity check. HTTP tools use `pytest-httpx` to mock responses; tools that call a vendor SDK stub the client with `unittest.mock.patch`. Tools are invoked exactly as the runtime invokes them — via LangChain `.ainvoke({...})` with a single input dict — and they return a **dict** (because `@serialize_pydantic_return` coerced the model).
```python src/modulex_integrations/tools//tests/test_.py
from __future__ import annotations
from typing import Any
import pytest
from modulex_integrations.tools.acme import TOOLS, list_tasks, manifest
API = "https://api.acme.example.com"
_AUTH: dict[str, Any] = {"auth_type": "bearer_token", "auth_data": {"token": "acme-fake"}}
def _args(**extra: Any) -> dict[str, Any]:
return dict(_AUTH, **extra)
class TestManifest:
def test_actions_match_tools_tuple(self) -> None:
assert {a.name for a in manifest.actions} == {t.name for t in TOOLS}
@pytest.mark.asyncio
async def test_list_tasks(httpx_mock): # type: ignore[no-untyped-def]
httpx_mock.add_response(
method="GET",
url=f"{API}/projects/p1/tasks?limit=30",
json={"tasks": [{"id": "t1", "title": "Ship docs", "status": "open"}]},
)
result = await list_tasks.ainvoke(_args(project_id="p1"))
assert result["success"] is True
assert result["tasks"][0]["id"] == "t1"
```
Run the suite, then the linters and type checker before opening a pull request:
```bash All tests
pytest
```
```bash One integration
pytest src/modulex_integrations/tools/acme/tests/
```
```bash Lint & type-check
ruff check src tests
mypy src/modulex_integrations
```
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4170 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** The author-to-runtime lifecycle of a custom ModuleX integration.
**[IMAGE_DETAILS]:** A left-to-right flow with five labeled stages: (1) author the directory (`manifest.py` / `tools.py` / `outputs.py` / `__init__.py`), (2) register the `modulex.tools` entry point in `pyproject.toml`, (3) `pip install` / package build, (4) runtime startup enumerates entry points and reads `manifest` + `TOOLS`, (5) the tool becomes callable from the LLM node, Agent node, Composer, and Assistant. Show the docs/CI filesystem-walk export branch as a side path feeding the catalog. 16:9, light and dark variants, ModuleX brand palette, no UI chrome.
## Validate the contract before you ship
Because every schema model uses `extra="forbid"`, an unknown or misspelled field fails when the module is imported. Importing `manifest.py` (or running `pytest`, which imports it) surfaces these errors immediately — there is no runtime-only failure mode for schema typos.
The integration name must be identical across the directory name, the manifest `name`, the entry-point key, and the `` segment of the entry-point value. Each `ActionDefinition.name` must equal a `@tool` function name listed in `TOOLS`. The test `assert {a.name for a in manifest.actions} == {t.name for t in TOOLS}` catches drift.
The `args_schema` is the authoritative list of what the tool accepts; the manifest `parameters` is descriptive. If a parameter reaches the upstream API, it should appear on the `args_schema`. Avoid documenting a parameter in the manifest that the function does not accept.
Use one of Pattern A / B / C consistently, set explicit timeouts on outbound calls, and never let the LLM see credential fields — the runtime strips `auth_type`, `auth_data`, `api_key`, `token`, `access_token`, and similar from the model-facing schema.
## Next steps
Every manifest field, type, and default; the six auth schema variants; `OAuthConfig`, `EnvVar`, `TestEndpoint`, and `BasicAuthSpec`.
Decorator order, the two auth conventions, output models, the three error patterns, and fully annotated GitHub, Slack, and Exa examples.
Connect an external MCP server and use its tools in ModuleX without packaging an integration.
How to open a pull request against `modulex-integrations` and what reviewers check.
---
# The @tool function contract
URL: https://docs.modulex.dev/integrations/building/tool-contract
The exhaustive @tool decorator contract for ModuleX integrations: the mandatory decorator order, the two auth-parameter conventions, typed Pydantic output models, the three error patterns, and worked GitHub, Slack, and Exa examples.
A ModuleX integration exposes its actions as **tools**: async Python functions
wrapped by a LangChain `StructuredTool`. Each tool pairs a Pydantic input model
(`args_schema`) with a typed Pydantic **output model** named as the function's
return annotation. This page is the exhaustive reference for that function
contract — the exact decorator stack and why its order is non-negotiable, the two
ways auth is injected, how the typed output model becomes the LLM-facing output
schema, the three error-handling patterns, and three fully worked examples
(GitHub, Slack, Exa).
For the metadata side of an integration — `IntegrationManifest`,
`ActionDefinition`, `ParameterDef`, and the six auth schema variants — see
[Manifest & schema contract](/integrations/building/manifest-schema). For the
end-to-end anatomy of an integration package, see
[Build an integration](/integrations/building/overview).
The **manifest** is not the source of truth for what a tool can be called with.
The callable surface — every parameter, its type and default — is defined by the
tool function's `args_schema`, not by the manifest's `parameters`. A manifest may
list fewer parameters than the function accepts. When the two disagree, the
`args_schema` wins. See [The args_schema is the callable
surface](#the-args_schema-is-the-callable-surface).
## Where a tool lives
Every integration lives at `src/modulex_integrations/tools//` and ships a
fixed set of files. The three you write a tool against are `tools.py`,
`outputs.py`, and `__init__.py`.
| File | Role in the tool contract |
| --- | --- |
| `tools.py` | The `args_schema` input models, the auth-header helper, and the `@tool` functions. |
| `outputs.py` | The typed Pydantic **output models** — one per action — used as each tool's return annotation. |
| `manifest.py` | Builds the single `IntegrationManifest` named `manifest`. Documented in [Manifest & schema contract](/integrations/building/manifest-schema). |
| `__init__.py` | Re-exports `manifest` and a `TOOLS` tuple — the only two names the runtime reads. |
| `dependencies.toml` | A `dependencies = [...]` list (often empty). |
### The module surface the runtime reads
The runtime imports your integration module and reads **exactly two names**:
- `manifest` — one `IntegrationManifest` instance.
- `TOOLS` — a tuple of the `@tool` objects (LangChain `StructuredTool`s), one per
action.
Nothing else in the module is part of the contract. A minimal `__init__.py`
re-exports both:
```python title="tools/github/__init__.py"
from modulex_integrations.tools.github.manifest import manifest
from modulex_integrations.tools.github.tools import (
create_issue,
list_repositories,
# ... one import per action
)
TOOLS = (create_issue, list_repositories) # ... all @tool objects
__all__ = ["manifest", "TOOLS", "create_issue", "list_repositories"]
```
ModuleX discovers integrations through the `modulex.tools` **entry-point group**
declared in the package's root `pyproject.toml`, not by importing files directly.
Registering a new integration means adding one entry-point line there. Discovery
and registration are covered in [Build an
integration](/integrations/building/overview).
## The @tool decorator stack
Every action is an `async def` wrapped by **two decorators, in a fixed order**.
```python title="The mandatory two-decorator stack"
from typing import Any
from langchain_core.tools import tool
from modulex_integrations import serialize_pydantic_return
@tool(args_schema=ListRepositoriesInput) # OUTER — applied last, closest to the call site
@serialize_pydantic_return # INNER — applied first, wraps the raw function
async def list_repositories(
auth_type: str,
auth_data: dict[str, Any],
visibility: str = "all",
# ... remaining typed parameters with defaults
) -> ListRepositoriesOutput: # return annotation = the Pydantic output model
...
return ListRepositoriesOutput(success=True, repositories=[...])
```
**The order is not stylistic — reversing it breaks the tool.** `@tool` must be the
**outer** decorator and `@serialize_pydantic_return` the **inner** one. Because
decorators apply bottom-up, `serialize_pydantic_return` wraps the raw function
first; `@tool` then wraps the dict-coercing version. Reverse them and `@tool` would
wrap the typed Pydantic-returning function, the dict coercion would never fire, and
serialization downstream would fail.
### What each decorator does
The LangChain decorator. It turns the function into a `StructuredTool` whose input
schema is the Pydantic model you pass as `args_schema`. The tool is invoked with a
single input dict via `await tool.ainvoke({...})`. `args_schema` is **required** for
every ModuleX tool — it is the callable surface (see below).
A ModuleX async wrapper (imported from the package root:
`from modulex_integrations import serialize_pydantic_return`). At run time, if the
function returns a Pydantic `BaseModel` it returns `result.model_dump()` — a plain
dict — instead. Non-`BaseModel` returns pass through unchanged. Crucially, it does
**not** change the function's return **annotation**: the annotation still points at
the Pydantic class, so static analysis and the backend's output-schema derivation
keep reading the model, while the runtime value becomes a JSON-serializable dict.
Returning a bare `BaseModel` broke the JSON boundary in the backend — a raw model
is not JSON-serializable, so `json.dumps()` raised a `TypeError`. The wrapper
dict-coerces the value at the tool boundary while preserving the typed annotation,
which the backend reads to derive the output schema. This is exactly why the
annotation must keep pointing at the model class even though the value at run time
is a dict — see [The output model becomes the output
schema](#the-output-model-becomes-the-output-schema).
## The args_schema is the callable surface
Each `@tool` takes a paired Pydantic input model via `args_schema=`. Its fields
**mirror the function parameters** — same names, same defaults. Required parameters
have no default; optional ones use `Field(default=..., description=...)`.
```python title="tools/github/tools.py — input model mirrors the signature"
from typing import Any
from pydantic import BaseModel, Field
class ListRepositoriesInput(BaseModel):
auth_type: str = Field(description="Authentication type (oauth2, bearer_token)")
auth_data: dict[str, Any] = Field(description="Authentication data containing tokens")
visibility: str = Field(default="all", description="all, public, or private")
affiliation: str = Field(
default="owner,collaborator,organization_member",
description="Comma-separated affiliations",
)
sort: str = Field(default="full_name", description="Sort field")
direction: str = Field(default="asc", description="Sort direction")
per_page: int = Field(default=30, description="Results per page")
page: int = Field(default=1, description="Page number")
```
**The manifest's `parameters` are NOT the callable surface — the `args_schema`
is.** A manifest's `ActionDefinition.parameters` may list fewer fields than the
function actually accepts. For example, GitHub's `create_issue` accepts and forwards
`assignees`, and `list_repositories` accepts `affiliation`, `direction`, and `page`
— all declared in the `args_schema` and reaching the upstream API — yet the manifest
omits them. When you document or call a tool, read the `args_schema`, not the
manifest. (Tracked as discrepancy D1.)
### How a tool is invoked
Tools are not called as plain functions. The runtime invokes them through LangChain
with a single input dict:
```python title="Invocation shape"
result = await create_issue.ainvoke({
"owner": "octocat",
"repo": "hello-world",
"title": "Track the docs rebuild",
"body": "First issue from a ModuleX tool.",
# auth params are injected by the runtime — see below
})
# result is a dict (serialize_pydantic_return dict-coerced the output model)
```
The returned value is a **dict** because `serialize_pydantic_return` coerced the
output model. The auth parameters are not passed by the caller — the runtime
injects them.
## Auth parameter patterns
A tool never receives raw credentials from the model. The model-facing schema omits
all credential fields (`api_key`, `token`, `auth_token`, `access_token`,
`bearer_token`, `auth_type`, `auth_data`); the runtime resolves the org's stored
credential and injects the auth parameters at call time. There are **two
conventions** for how those parameters appear on the function signature.
The first two parameters are the auth pair: `auth_type: str` and
`auth_data: dict[str, Any]`. A module-level helper builds provider headers by
branching on `auth_type`.
```python title="tools/github/tools.py — header helper"
def _get_auth_headers(auth_type: str, auth_data: dict[str, Any]) -> dict[str, str]:
headers = {"Accept": "application/vnd.github+json"}
if auth_type == "oauth2":
access_token = auth_data.get("access_token") # oauth2 reads access_token
if access_token:
headers["Authorization"] = f"Bearer {access_token}"
elif auth_type == "bearer_token":
token = auth_data.get("token") # bearer_token reads token
if token:
headers["Authorization"] = f"Bearer {token}"
return headers
```
The two `auth_type` string values these integrations accept are `oauth2` and
`bearer_token`, matching the two `auth_schemas` the manifest declares
(`OAuth2AuthSchema` + `BearerTokenAuthSchema`).
Some integrations take a single `api_key: str` as the second parameter instead of
the auth pair. The runtime auto-fills any parameter whose **name** matches a key in
the resolved credential, so a parameter named `api_key` receives the resolved key
(from either an `api_key` or a `modulex_key` credential) directly.
```python title="tools/exa/tools.py — header helper"
def _headers(api_key: str) -> dict[str, str]:
return {"x-api-key": api_key, "Content-Type": "application/json"}
@tool(args_schema=SearchInput)
@serialize_pydantic_return
async def search(query: str, api_key: str, num_results: int = 10) -> SearchOutput:
...
```
Exa's manifest declares `ApiKeyAuthSchema` + `ModulexKeyAuthSchema` for this
convention.
**How the runtime injects auth.** Before calling the tool, the runtime strips the
credential fields from the model-facing schema (so the LLM never sees them), then
auto-fills any signature parameter whose name matches a key in the resolved
credential's data — `api_key`, `token`, `access_token`, and so on land on the
matching parameter; the `auth_type`/`auth_data` pair is injected for tools that
declare it. The full credential-resolution path — encryption, the OAuth2 PKCE flow,
the six auth schema variants, and credit gating on `modulex_key` resolution — is
documented in [Integration authentication &
credentials](/integrations/authentication).
Both auth conventions appear in the catalog today, but a manifest's auth schema and
the function signature must agree: declare `oauth2` / `bearer_token` schemas with
the `auth_type` + `auth_data` pair, and declare `api_key` / `modulex_key` schemas
with a named `api_key` parameter. The `custom` and `internal` auth variants have no
reference integration among GitHub, Slack, or Exa, so their signature shape is not
demonstrated here — `internal` is a reserved variant with no shipped catalog usage.
## Typed Pydantic output models
Each tool's return annotation is a typed output model defined in `outputs.py`.
Every output model subclasses a private base configured with
`model_config = ConfigDict(extra="forbid")`, so an unexpected field fails fast.
There are two layers of model.
```python title="tools/github/outputs.py — the two layers"
from pydantic import BaseModel, ConfigDict, Field
class _Base(BaseModel):
model_config = ConfigDict(extra="forbid")
# Layer 1 — nested resource model. Fields are intentionally permissive
# (X | None = None) because the upstream API omits fields.
class IssueCreated(_Base):
number: int | None = None
title: str | None = None
body: str | None = None
state: str | None = None
url: str | None = None
created_at: str | None = None
# Layer 2 — per-action output wrapper carrying the success flag + payload.
class CreateIssueOutput(_Base):
success: bool # required; no `error` field — this model raises on failure
issue: IssueCreated
```
**Universal.** Every output model carries `success: bool` as the one stable,
cross-integration field. It is required.
**Conditional.** Present only on integrations whose error model returns a failure
payload rather than raising — see the table below. Do not assume every tool returns
an `error` field.
**`error` field presence is integration-dependent.** A generic "tool output" claim
that every tool returns `{success, error}` is wrong: GitHub's models have **no**
`error` field (failures raise before a model is constructed), while Slack and Exa
both carry `error: str | None`. The only field you can rely on across every
integration is `success: bool`. (Tracked as discrepancy D6.)
| Integration | `success` | `error` field | Why |
| --- | --- | --- | --- |
| GitHub | `success: bool` (required) | **Absent** | Failures raise before the model is built. |
| Slack | `success: bool` | `error: str \| None = None` | Failure path returns a `success=False` model. |
| Exa | `success: bool` | `error: str \| None = None` | All exceptions are caught and returned as a model. |
### The output model becomes the output schema
The output **shape** is deliberately **not** declared in the manifest. Neither
`ActionDefinition` nor `IntegrationManifest` carries an `output_schema` field — a
reader of the manifest alone will not find output shapes; they live in `outputs.py`.
(Tracked as discrepancy D2.)
Instead, the backend derives the output schema at startup from the `@tool`
function's **return annotation**:
The loader resolves the tool's underlying coroutine (the function wrapped by
`@tool`).
It calls `typing.get_type_hints(func)` to resolve the stringified
`-> CreateIssueOutput` return annotation. This is why
`serialize_pydantic_return` must preserve the annotation even though it dict-coerces
the value.
If the resolved return type has `model_json_schema()`, the loader sets the action's
output schema to `return_type.model_json_schema()`.
The chain is the whole reason the decorator order is mandatory: the model-facing
output schema comes from the **annotation**, while the JSON-serializable value comes
from the **dict coercion**. `@tool` outer + `@serialize_pydantic_return` inner is
what lets both be true at once.
## The three error patterns
A tool function must decide what happens on an upstream failure. The three
reference integrations demonstrate the three sanctioned patterns. Pick one and apply
it consistently across all of an integration's tools.
Call `response.raise_for_status()` after each request and only ever construct
`success=True` models. HTTP errors propagate as exceptions; the runtime handles
them. Output models have **no** `error` field.
```python title="Pattern A — raise on non-2xx"
async with httpx.AsyncClient() as client:
response = await client.post(url, headers=headers, json=payload)
response.raise_for_status() # non-2xx raises here
data = response.json()
return CreateIssueOutput(success=True, issue=IssueCreated(...))
```
Use this when the upstream API returns proper HTTP status codes and you want
failures surfaced as exceptions.
Some APIs return **HTTP 200** with an `{"ok": false, "error": "..."}` body. Read the
JSON, check the success flag, and on the failure branch return the output model with
`success=False` and `error` set; the success branch leaves `error` as `None`. Do
**not** call `raise_for_status()` here — inspect the body instead.
```python title="Pattern B — check the body, not the status"
data = response.json()
if not data.get("ok"):
return ListChannelsOutput(
success=False,
error=data.get("error", "Unknown error"),
)
# success branch populates fields; error stays None
return ListChannelsOutput(success=True, channels=[...])
```
Wrap every call in `try/except` so non-2xx responses, timeouts, and unexpected
exceptions all surface as `success=False` + `error` and **never** raise. Validate
inputs (such as a present `api_key`) before any HTTP call, and set explicit
per-endpoint timeouts.
```python title="Pattern C — catch everything, return a model"
if not api_key or not api_key.strip():
return SearchOutput(success=False, error="Exa API key is empty.") # pre-check
try:
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.post(f"{_EXA_API_BASE}/search", headers=..., json=payload)
if response.status_code != 200:
return SearchOutput(
success=False,
error=f"Exa API error ({response.status_code}): {response.text}",
)
data = response.json()
except httpx.TimeoutException:
return SearchOutput(success=False, error="Request timed out.")
except Exception as exc:
return SearchOutput(success=False, error=f"Search failed: {exc}")
return SearchOutput(success=True, results=[...])
```
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4190 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** Decision diagram mapping the three tool error patterns to when each is used.
**[IMAGE_DETAILS]:** Three labeled columns — A "raise" (GitHub), B "inline ok:false" (Slack), C "try/except" (Exa). For each, show the trigger (proper HTTP status codes / HTTP 200 with `ok:false` body / any failure must be non-raising), the action taken (`response.raise_for_status()` / check `data["ok"]` / wrap in try/except + pre-validate), and the resulting output-model shape (no `error` field / `success=False` + `error` / `success=False` + `error`). Add a footer note: "`success: bool` is universal; `error` exists only on B and C." Light theme, 16:9, monospace for code tokens.
## Worked example — GitHub `create_issue` end to end
This ties the whole contract together: the input model, the output model, and the
`@tool` function, with the manifest action for context.
```python tools.py
from typing import Any
import httpx
from langchain_core.tools import tool
from pydantic import BaseModel, Field
from modulex_integrations import serialize_pydantic_return
from modulex_integrations.tools.github.outputs import (
CreateIssueOutput,
IssueCreated,
)
class CreateIssueInput(BaseModel):
auth_type: str = Field(description="Authentication type")
auth_data: dict[str, Any] = Field(description="Authentication data")
owner: str = Field(description="Repository owner")
repo: str = Field(description="Repository name")
title: str = Field(description="Issue title")
body: str | None = Field(default=None, description="Issue body/description")
labels: list[str] | None = Field(default=None, description="List of label names")
assignees: list[str] | None = Field(default=None, description="Usernames to assign")
@tool(args_schema=CreateIssueInput) # OUTER
@serialize_pydantic_return # INNER
async def create_issue(
auth_type: str,
auth_data: dict[str, Any],
owner: str,
repo: str,
title: str,
body: str | None = None,
labels: list[str] | None = None,
assignees: list[str] | None = None,
) -> CreateIssueOutput: # annotation read by the loader
"""Create an issue in a repository."""
headers = _get_auth_headers(auth_type, auth_data)
payload: dict[str, Any] = {"title": title}
if body:
payload["body"] = body
if labels:
payload["labels"] = labels
if assignees:
payload["assignees"] = assignees
async with httpx.AsyncClient() as client:
response = await client.post(
f"https://api.github.com/repos/{owner}/{repo}/issues",
headers=headers,
json=payload,
)
response.raise_for_status() # Pattern A
i = response.json()
return CreateIssueOutput(
success=True,
issue=IssueCreated(
number=i.get("number"),
title=i.get("title"),
body=i.get("body"),
state=i.get("state"),
url=i.get("html_url"), # wire field html_url -> model field url
created_at=i.get("created_at"),
),
)
```
```python outputs.py
from pydantic import BaseModel, ConfigDict
class _Base(BaseModel):
model_config = ConfigDict(extra="forbid")
class IssueCreated(_Base):
number: int | None = None
title: str | None = None
body: str | None = None
state: str | None = None
url: str | None = None
created_at: str | None = None
class CreateIssueOutput(_Base):
success: bool
issue: IssueCreated
```
```python manifest.py (action excerpt)
from modulex_integrations.schema import ActionDefinition, ParameterDef
ActionDefinition(
name="create_issue", # must match ^[a-z][a-z0-9_]*$
description="Create a new issue",
parameters={
"owner": ParameterDef(type="string", description="Repository owner", required=True),
"repo": ParameterDef(type="string", description="Repository name", required=True),
"title": ParameterDef(type="string", description="Issue title", required=True),
"body": ParameterDef(type="string", description="Issue body"), # required defaults to False
"labels": ParameterDef(type="array", description="Issue labels"),
# NOTE: `assignees` is intentionally absent here but present in the
# args_schema and forwarded to the API — the args_schema is canonical.
},
)
```
The GitHub API field `html_url` is mapped onto the model's `url` field; similar
wire-to-model remapping appears across the integration (for example
`stargazers_count` becomes `stars`). Map upstream field names to your model field
names explicitly in the tool body.
## Worked example — Slack `post_message`
Slack uses the **inline `ok:false`** error pattern (Pattern B) and an output model
that carries both `success` and `error`. Required input fields (`channel_id`,
`text`) have no default.
```python tools.py
@tool(args_schema=PostMessageInput)
@serialize_pydantic_return
async def post_message(
auth_type: str,
auth_data: dict[str, Any],
channel_id: str,
text: str,
) -> PostMessageOutput:
"""Post a message to a Slack channel."""
headers = _get_auth_headers(auth_type, auth_data)
async with httpx.AsyncClient() as client:
response = await client.post(
"https://slack.com/api/chat.postMessage",
headers=headers,
json={"channel": channel_id, "text": text},
)
data = response.json() # no raise_for_status — Slack returns 200
if not data.get("ok"):
return PostMessageOutput(success=False, error=data.get("error", "Unknown error"))
return PostMessageOutput(success=True, ts=data.get("ts"), channel=data.get("channel"))
```
```python outputs.py
class PostMessageOutput(_Base):
success: bool
error: str | None = None
ts: str | None = None
channel: str | None = None
```
Slack returns HTTP 200 even for failures, so the tool checks `data["ok"]` rather
than the status code. A failure such as `{"ok": false, "error": "channel_not_found"}`
becomes `PostMessageOutput(success=False, error="channel_not_found")`. Slack's
migrated output models also flatten the legacy `{"success", "action", "result": {...}}`
wrapper — there is no `result` or `action` key on the package output.
## Worked example — Exa `search`
Exa uses the **single `api_key` parameter** auth convention and the
**try/except wrapper** error pattern (Pattern C). Every failure becomes a model;
nothing raises.
```python tools.py
_EXA_API_BASE = "https://api.exa.ai"
_SEARCH_TIMEOUT = 30.0
@tool(args_schema=SearchInput)
@serialize_pydantic_return
async def search(query: str, api_key: str, num_results: int = 10) -> SearchOutput:
"""Run a neural search over the web with Exa."""
if not api_key or not api_key.strip():
return SearchOutput(success=False, error="Exa API key is empty.")
payload = {"query": query, "numResults": num_results}
try:
async with httpx.AsyncClient(timeout=_SEARCH_TIMEOUT) as client:
response = await client.post(
f"{_EXA_API_BASE}/search",
headers=_headers(api_key),
json=payload,
)
if response.status_code != 200:
return SearchOutput(
success=False,
error=f"Exa API error ({response.status_code}): {response.text}",
)
data = response.json()
except httpx.TimeoutException:
return SearchOutput(success=False, error="Request timed out.")
except Exception as exc:
return SearchOutput(success=False, error=f"Search failed: {exc}")
return SearchOutput(
success=True,
results=[SearchResult(**r) for r in data.get("results", [])],
)
```
```python outputs.py
class SearchResult(_Base):
title: str | None = None
url: str | None = None
text: str | None = None
score: float | None = None
class SearchOutput(_Base):
success: bool
error: str | None = None
results: list[SearchResult] = Field(default_factory=list)
```
Exa takes `api_key` directly rather than the `auth_type`/`auth_data` pair, and it
catches every exception so the agent always receives a structured model. It also
sets explicit per-endpoint timeouts (search uses `30.0s`; content fetches use a
longer timeout). Pricing figures in Exa's README are approximate and live only in
prose — they are not encoded in any manifest or output field, and managed-key usage
is metered in ModuleX credits; see [Credits & metering](/billing/credits).
## Contract checklist
Before you register an integration, confirm each tool satisfies the contract.
`@tool(args_schema=...)` is the outer decorator; `@serialize_pydantic_return` is the
inner one. The function is `async def`.
The `args_schema` model's fields match the function parameters (names + defaults).
Required parameters have no default. Remember the `args_schema` — not the manifest —
is the callable surface.
Use `auth_type` + `auth_data` for `oauth2` / `bearer_token` schemas, or a named
`api_key` parameter for `api_key` / `modulex_key` schemas. Never accept raw
credentials from the model.
The return annotation is a Pydantic model from `outputs.py` (a subclass of your
`extra="forbid"` base). Every model has `success: bool`; add `error: str | None`
only if your error pattern returns a failure model.
Choose Pattern A (raise), B (inline `ok:false`), or C (try/except) and use it across
all of the integration's tools.
`manifest` and `TOOLS` are re-exported, and every `@tool` object is in `TOOLS`.
Do not advertise per-tool `pip install` extras (such as `[github,slack]` or `[all]`)
for your integration. The packaging extras are currently empty — installing them
emits pip warnings and installs only the core package. Until the dependency-assembly
step ships, integration dependencies belong in your `dependencies.toml` and the core
install. See [Installing & using
integrations](/integrations/install).
## Next steps
The metadata side: `IntegrationManifest`, `ActionDefinition`, `ParameterDef`, and
the six auth schema variants.
The full package anatomy and how an integration is discovered and registered.
How the runtime resolves and injects the credentials your tool's auth parameters
receive.
Expose tools from an external MCP server instead of authoring a Python integration.
---
# Browse the integration catalog
URL: https://docs.modulex.dev/integrations/catalog
Browse all 175 ModuleX integrations by category, search for a service, and learn how to read a tool's catalog page before you connect it.
The catalog is the directory of everything ModuleX can connect to. Each entry is an **integration** — a connector to an outside service such as Slack, GitHub, or Salesforce — and each integration exposes one or more **tools**, the individual actions your workflows and the Assistant can call.
ModuleX ships **175 integrations** today. Browse them by category, search for the service you need, then open its page to see what it can do before you connect it.
New to integrations? Start with [the integrations overview](/integrations/overview) for the bigger picture of how connectors, tools, and credentials fit together. This page is for finding a specific integration once you know you want one.
## What counts as an integration
An integration packages everything ModuleX needs to talk to one service:
How ModuleX signs in to the service on your behalf — an API key, an OAuth connection, or a managed key. You set this up once as a credential.
The individual actions the integration can perform — "send a message", "create an issue", "search records". One integration usually exposes several tools.
A generated reference page that lists every tool, its inputs, how it authenticates, and any limits — so you know what you are connecting before you connect it.
The service's display name, logo, and link to its own site, so the catalog stays easy to scan.
Once an integration is connected, its tools become available to your workflows through the [Tool node](/workflow-builder/nodes/tool) and to the [Assistant](/assistant/overview) when it works through a task.
## Browse by category
Each integration is tagged with one or more categories so you can scan the catalog by the kind of work you do rather than by remembering exact product names. The largest groups are:
Team and document tools — messaging, calendars, docs, and project trackers. The largest group in the catalog.
Source control, cloud platforms, observability, and deployment services.
Email, campaigns, analytics, and audience tools.
Customer records, pipelines, and outreach platforms.
Connectors that move data between other services and trigger downstream work.
Payments, data warehouses, AI services, support desks, and many more specialised connectors.
Categories are a browsing aid, not a fixed taxonomy. Each integration sets its own categories, so the exact labels and counts shift as the catalog grows. Use search when you already know the service you want.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4040 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The integration catalog in the ModuleX app, showing the category sidebar and a grid of integration cards.
**[SCREENSHOT_DETAILS]:** Capture the catalog/browse view in the live app with the category filter visible on the left and integration logo cards on the right. Show the search box at the top. Light theme, 16:9, no personal data.
## Find an integration
In the app, go to the integrations area and open **Browse**. You'll see every available integration as a card with its logo and a short description.
Type the service name in the search box, or pick a category to narrow the grid. Search matches the display name and description, so "email", "calendar", or "database" all surface relevant results.
Click a card to open its catalog page. Review the tools it exposes and how it authenticates before you connect it.
Add a credential for the integration, then use its tools from a workflow or the Assistant. See [connect an integration](/guides/connect-an-integration) for the full walkthrough.
## What's on a tool's catalog page
Every integration has its own page, generated directly from the integration's manifest so it always matches what the service actually exposes. When you open one, you'll find:
The service's display name, logo, a short description of what it does, and a link to the service's own website.
Every tool the integration exposes, each with a plain description, its inputs (name, type, and whether each is required), and the shape of what it returns. This is the menu your workflows and the Assistant choose from.
How the integration signs in — an API key, an OAuth connection, or a ModuleX-managed key — and any setup steps or values you need to provide. See [authentication & credentials](/integrations/authentication) for how each method works.
Service-specific rate limits, size caps, and other constraints to keep in mind, drawn from the integration's own notes.
Who maintains the integration. Most are maintained by ModuleX.
Catalog pages are generated from each integration's manifest, not written by hand. If a page looks out of date, the fix is to update the source integration and regenerate — the page will follow.
## Browse the catalog from code
You can also list the catalog programmatically — useful for building your own picker or syncing the available integrations into another tool. The browse endpoint returns the integrations available to your organization.
Every request authenticates with `Authorization: Bearer mx_live_…` plus your `X-Organization-ID`. See [authentication](/api-reference/authentication) for how to get and use these.
```bash cURL
curl https://api.modulex.dev/integrations/browse \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: org_your_org_id"
```
```python Python
import asyncio
from modulex import Modulex
async def main():
async with Modulex(
api_key="mx_live_your_api_key",
organization_id="org_your_org_id",
) as client:
catalog = await client.integrations.browse()
for integration in catalog:
print(integration.name, integration.display_name)
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_your_api_key",
organizationId: "org_your_org_id",
});
const catalog = await client.integrations.browse();
for (const integration of catalog) {
console.log(integration.name, integration.displayName);
}
```
Browsing the catalog returns the integrations you can connect — it does not connect anything or move data. To work with credentials, see [managing credentials](/integrations/managing-credentials).
## Don't see what you need
Point ModuleX at an external Model Context Protocol server to use its tools alongside the built-in catalog.
Author a new integration and expose its tools to ModuleX.
Connecting a custom MCP server is a separate path from the built-in catalog above — it is not one of the 175 catalog integrations. Use it when the service you need isn't listed.
## Next steps
How connectors, tools, and credentials work together.
A step-by-step walkthrough from connecting to calling a tool.
The connection methods every integration uses.
---
# Installing & using integrations
URL: https://docs.modulex.dev/integrations/install
How ModuleX integrations are discovered through Python entry points, how to install the modulex-integrations package and its tool SDK dependencies, and the difference between managed and bring-your-own-key tool usage.
ModuleX integrations are connectors to external services. Each **integration** (for example `github`) ships a manifest plus a set of **tools** — the callable actions you run from a workflow's [Tool node](/workflow-builder/nodes/tool) or from the Assistant. The full set of integrations lives in one installable Python distribution, **`modulex-integrations`**, which the ModuleX backend loads at startup.
This page is for people running or extending the ModuleX backend: it covers how integrations are discovered at runtime, how to install the package and the per-tool SDK dependencies you actually need, and how a tool call is authenticated either with ModuleX-managed credentials or your own key. If you only want to connect a service in the app, see [Authentication & credentials](/integrations/authentication) and [Connect an integration](/guides/connect-an-integration) instead — you do not install anything for that.
The hosted ModuleX service already runs `modulex-integrations` for you. You install the package yourself only when you self-host the backend or develop integrations locally. To author a new integration, start at [Build an integration](/integrations/building/overview).
## How integrations load at runtime
Integrations are not configured by hand or read from a directory you point at. They are discovered through standard Python **entry points** in the group `modulex.tools`. Every integration in the package declares one entry point that maps its catalog name to its module:
```toml pyproject.toml
[project.entry-points."modulex.tools"]
aws = "modulex_integrations.tools.aws"
github = "modulex_integrations.tools.github"
slack = "modulex_integrations.tools.slack"
# ... 175 entries total
```
At startup the backend enumerates this group, imports each module, and reads two required symbols from it:
The integration's manifest — name, display name, categories, actions, and auth schemas. Defined in `manifest.py` and re-exported from the package `__init__.py`. See the [manifest & schema contract](/integrations/building/manifest-schema).
A tuple of LangChain tool objects, one per action. See the [`@tool` function contract](/integrations/building/tool-contract).
The mapping key (for example `github`) is the integration's catalog and credential name. The mapping value (for example `modulex_integrations.tools.github`) is the **package module**, not the tools module — the runtime appends `.tools` to it when it needs to import the callable (resolving to `modulex_integrations.tools.github.tools`).
The backend calls `entry_points(group="modulex.tools")` to list every registered integration.
For each entry point it imports the module and reads `manifest` and `TOOLS`.
The resolved catalog is cached for the lifetime of the worker process. A newly installed package version is not picked up until you restart the worker.
Because the catalog is cached per process, upgrading `modulex-integrations` while a worker is running has no effect until that worker restarts. Restart all backend workers after installing or upgrading the package.
### Two catalog sources
The runtime resolves tools from two places, and entry points are not the only one:
- **Package entry points** — the `modulex.tools` group described above. This is the primary source and **wins on a name collision**.
- **Legacy on-disk JSON** — a small set of integrations not yet migrated to the package, loaded from `*_integration.json` files in the backend. The Model Context Protocol connector (`mcp_server`) is handled this way rather than as a package entry point. See [Custom MCP servers](/integrations/building/custom-mcp).
So "every tool comes from `modulex-integrations`" is almost true — treat the legacy JSON integrations as documented exceptions.
There are **two distinct discovery mechanisms** in this system, and they are not interchangeable. The runtime uses **entry points** (above). The documentation and CI pipeline that generates the [integration catalog](/integrations/catalog) instead walks the filesystem for `tools/*/manifest.py`, using the entry-point table only as a cross-check. If you are reading manifests for tooling, match the mechanism to your goal.
## Install the package
`modulex-integrations` requires **Python 3.12 or newer**. The base install pulls in only three core dependencies — `pydantic`, `httpx`, and `langchain-core` — which is everything most integrations need.
```bash pip
pip install modulex-integrations
```
```bash uv
uv pip install modulex-integrations
```
The backend pins an exact version of this package (it does not float with `>=`), because the manifest schema can change between minor versions and the runtime rejects unknown manifest fields at import time. When self-hosting, install the version that matches the backend you are running rather than the latest release.
### Do not rely on install extras
The package declares an `all` extra and the README advertises per-tool extras such as `[github,slack]`. **Do not use them.** They do not work as written today:
The `all` extra is an **empty list** in the package, and there are **no per-tool extras** (`[github]`, `[slack]`, `[aws]`, and so on are not defined). Installing them does not add any tool SDKs:
- `pip install "modulex-integrations[all]"` installs only the three core dependencies — the same as the base install.
- `pip install "modulex-integrations[github,slack]"` emits pip warnings like `WARNING: modulex-integrations does not provide the extra 'github'` and installs only the base package.
A script to auto-assemble these extras from each tool's declared dependencies is planned but **not implemented**. Until it lands, treat `[all]` and per-tool extras as non-functional and install tool SDKs manually (below).
This limitation is also recorded in [Known limitations](/reference/known-limitations) and the [Help known-limitations page](/help/known-limitations).
### Install tool SDK dependencies manually
Because extras are inert, the working path is: install the base package, then install whatever client SDK each integration you intend to use needs. Many integrations need **nothing extra** — they call their service over plain HTTP through the core `httpx` dependency. For example, both `github` and `slack` declare no additional dependencies.
Others do need a vendor SDK. Each integration declares what it needs in a `dependencies.toml` file in its source directory:
```toml src/modulex_integrations/tools/aws/dependencies.toml
dependencies = ["boto3>=1.34.0"]
```
Install those yourself. For an AWS-backed workflow, for example:
```bash
pip install modulex-integrations boto3
```
There is **no REST endpoint that runs a tool directly**. Tools execute only inside workflow runs and Assistant/Composer turns. Installing the package makes the catalog available to the backend; you call individual tools through the [Tool node](/workflow-builder/nodes/tool), the Assistant, or the AI Composer.
## Managed usage vs bring-your-own-key
Whether a tool needs an SDK installed is separate from **how it is authenticated and billed**. Every tool call resolves a [credential](/integrations/managing-credentials) for the integration in your organization, and that credential is one of two kinds.
The call runs through a ModuleX-provisioned key from a managed pool. Usage is **metered in credits** and is subject to the billing gate. The managed providers appear on the wire as `modulexai` (models) and `modulexdb` (knowledge); managed tool calls draw from your credit balance.
You connect your own provider account. Usage is billed **directly by that provider with no ModuleX markup**, and BYOK calls are **not** charged in ModuleX credits — they are tracked for analytics only. BYOK is available on every plan; there is no entitlement that gates it.
The runtime injects the resolved credential into the tool call internally, so the model and the tool function never see raw secrets. The behavior differs by credential kind:
Before the call runs, the runtime checks the organization's credit limit (without recording yet). If the monthly budget is exhausted and no wallet overage is available, the call is denied. On success it records the per-call tool cost. See [Credits & metering](/billing/credits).
The runtime decrypts your stored credential, refreshes the OAuth2 token if it is close to expiry, and runs the call. There is **no credit check or credit charge** — only usage tracking.
ModuleX-managed tool calls are part of the live billing gate. When the credit limit is exhausted, a managed call is denied rather than running. Plan for this in any workflow that depends on managed tool usage. BYOK calls are never credit-gated.
For how a tool resolves credentials, refreshes OAuth2 tokens, and maps auth into the call, see [Credentials & OAuth2](/concepts/credentials-oauth) and [Authentication & credentials](/integrations/authentication). For model and knowledge providers specifically, see [LLM providers](/integrations/llm-providers/overview) and [Knowledge providers](/integrations/knowledge-providers/overview).
## Verify the catalog loaded
After installing the package and restarting your workers, confirm the integrations you expect are present. The catalog the backend exposes reflects the entry points found at startup.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4010 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The integrations catalog in the ModuleX app after the package has loaded, showing connected and available integrations.
**[SCREENSHOT_DETAILS]:** Capture the integrations catalog page in the live ModuleX app. Show the grid of integrations with a few connected (credential present) and the rest available to connect. Dark theme, full-width, no personal data. Highlight that the count reflects the installed package, not a hardcoded list.
If an integration you expect is missing, check, in order:
The catalog is cached per process. Restart all backend workers after installing or upgrading `modulex-integrations`.
The backend pins an exact version. A mismatched install can fail to import a manifest with an unknown field, because the schema rejects unknown fields at import time. Install the version that matches your backend.
An integration whose `dependencies.toml` lists a vendor SDK will fail to load its tools if that SDK is missing, because extras do not install it for you. Install the SDK manually (see above). The integration's manifest may still appear while individual actions fail to load.
A few integrations (such as `mcp_server`) load from legacy on-disk JSON, not from the package entry points. See [Custom MCP servers](/integrations/building/custom-mcp).
## Next steps
Connect a service with an API key or OAuth2 and store the credential.
See every integration ModuleX can connect to, grouped by category.
Call an integration's action from the Tool node.
Author your own integration and expose its tools.
---
# modulexdb — the ModuleX-managed vector store
URL: https://docs.modulex.dev/integrations/knowledge-providers/modulexdb
modulexdb is the ModuleX-managed vector store: a fully hosted pgvector store with managed embeddings, used as the knowledge provider for a knowledge base or a workflow knowledge node. Reference for the provider config (every field, type, and default), the credit cost of ingest and retrieval, and the billing gate that returns 402/403/429.
`modulexdb` is the **ModuleX-managed vector store** — the built-in knowledge provider you
select when you want ModuleX to host the vectors and run the embeddings for you, with no
external vector database to provision. It is one of the [knowledge
providers](/integrations/knowledge-providers/overview) ModuleX can retrieve from; the others
([Qdrant](/integrations/knowledge-providers/qdrant),
[Pinecone](/integrations/knowledge-providers/pinecone),
[MongoDB Atlas](/integrations/knowledge-providers/mongodb-atlas), and
[Weaviate](/integrations/knowledge-providers/weaviate)) are bring-your-own-key (BYOK) stores
that you connect with your own credentials.
Choosing `modulexdb` is the difference between **managed** and **BYOK** retrieval. When a
[knowledge base](/platform/knowledge/overview) embeds on the managed pool, ModuleX
provisions the embedding model, stores the vectors in pgvector, serves retrieval, and
**meters that work in [credits](/billing/credits)**. BYOK providers are **never credited**
— that usage is billed by your upstream vector store and embedding provider.
This page is the **provider-catalog entry** for `modulexdb`: how to select it as a provider
for a knowledge base and for a [workflow knowledge node](/workflow-builder/nodes/knowledge),
what it costs, and how the billing gate behaves. The exhaustive reference for the managed
store itself — the full embedding and chunking schema, the ingest and retrieval pipelines,
document and chunk records, and the per-operation REST surface — is
[Managed knowledge (modulexdb)](/platform/knowledge/managed). Read that page for the deep
mechanics; this page tells you how to wire `modulexdb` in.
## When to choose modulexdb
ModuleX hosts the vectors in pgvector and provisions the embedding model. No external
store to run. Ingest and retrieval are billed in credits. Best when you want RAG to work
out of the box.
You bring the vector store and the embedding credential. ModuleX queries it on your
behalf. Usage is not credited by ModuleX — your provider bills you directly. Best when
you already run a vector database.
A knowledge base is **managed** when its `embedding_config.integration_name` is `modulexai`
(the managed integration name on the wire). The provider name `modulexdb` is how the same
managed store is referenced from a [knowledge node](/workflow-builder/nodes/knowledge) and
in the provider catalog. Both point at the same hosted pgvector store; everything on this
page about credit cost and the billing gate applies **only** to it.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4120 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** Managed vs BYOK knowledge provider decision diagram for ModuleX.
**[IMAGE_DETAILS]:** Two columns. Left: "modulexdb (managed)" with sub-items "ModuleX-hosted pgvector", "managed embeddings", "billed in credits". Right: "BYOK (Qdrant / Pinecone / Atlas / Weaviate)" with "your vector store", "your embedding credential", "not credited by ModuleX". A shared box at the top reads "Knowledge base / knowledge node". Light theme, 16:9, brand palette.
## Selecting modulexdb for a knowledge base
You select the managed store at the knowledge-base level through `embedding_config`. Set
`integration_name` to `modulexai` and ModuleX treats the knowledge base as managed; on
create it also auto-creates a linked credential so [workflow knowledge
nodes](/workflow-builder/nodes/knowledge) can reference the knowledge base by
`credential_id`.
The ModuleX integration that owns the embedding pool. Set to `modulexai` to make the
knowledge base **managed** (`modulexdb`, billed in credits). Any other value — for example
`openai` or `cohere` — is treated as BYOK and is not credited. This single field is what
decides managed vs BYOK.
The actual embedding provider behind the managed pool. Validated against `openai`,
`cohere`, `azure`, `huggingface`, but only `openai` and `cohere` have an embedding
implementation; any other value raises `Unsupported embedding provider` at embed time.
Also accepted under the key `provider`.
The embedding model. Also accepted under the key `model`. For managed knowledge bases the
model resolves through the ModuleX model pool so that ingest-time and search-time vectors
come from the same model.
The embedding vector dimension. Range `64`–`4096`. The pgvector column is sized for the
default `1536` (the `text-embedding-3-small` dimension). Out-of-range values are rejected
at create or update with a `KnowledgeBaseValidationError` → `400`.
The embedding credential. Also accepted as `provider_credential_id`. If omitted, ModuleX
auto-discovers an org credential whose integration exposes an embedding-capable model. If
none exists, create fails with `NoEmbeddingCredentialError` → `400`.
**Two accepted key spellings.** ModuleX reads `embedding_config` defensively: `provider` or
`provider_id`, `model` or `model_id`, `provider_credential_id` or `credential_id`. The
managed-vs-BYOK decision is made **only** on `integration_name == "modulexai"`, so a managed
knowledge base must set `integration_name`.
A managed `embedding_config` looks like this:
```json
{
"integration_name": "modulexai",
"provider_id": "openai",
"model_id": "text-embedding-3-small",
"dimension": 1536,
"credential_id": "a1b2c3d4-0000-4000-8000-000000000001"
}
```
For the chunking schema, document and chunk records, storage backends, and the full
ingest and retrieval pipelines, see
[Managed knowledge (modulexdb)](/platform/knowledge/managed).
## Selecting modulexdb in a workflow knowledge node
A [knowledge node](/workflow-builder/nodes/knowledge) retrieves from a provider inside a
running workflow. To retrieve from the managed store, set the node's `provider_type` to
`modulexdb` and point `credential_id` at the managed knowledge base's linked credential.
`modulexdb` is the **default** `provider_type` for a knowledge node.
The credential ID for the knowledge base. For `modulexdb` this is the credential ModuleX
auto-created when the managed knowledge base was created. ModuleX resolves the knowledge
base from the credential's stored `knowledge_base_id`.
The knowledge provider. One of `modulexdb`, `qdrant`, `pinecone`, `weaviate`,
`mongodb_atlas`. Use `modulexdb` for the managed store. The external values require a
BYOK credential and, for most of them, a `collection_name`.
Number of results to retrieve. Range `1`–`20`.
Minimum cosine-similarity score threshold. Range `0.0`–`1.0`. Matches below this score are
dropped.
Maximum tokens in the formatted context string, when the node returns a RAG context.
Range `100`–`8000`.
Collection or index name. **Not used** for `modulexdb` (the managed store needs no
collection). Required for external providers such as Qdrant and Pinecone.
Namespace for Pinecone or similar providers. **Not used** for `modulexdb`.
Embedding configuration for external providers that do not embed internally. **Not used**
for `modulexdb`, which carries its own `embedding_config` on the knowledge base.
A managed knowledge-node config:
```json
{
"credential_id": "939f74dc-7b2f-473c-b87d-b95c30c32fd3",
"provider_type": "modulexdb",
"top_k": 5,
"min_score": 0.3
}
```
## Credit cost of managed knowledge
`modulexdb` is the only knowledge provider that consumes [credits](/billing/credits). A
credit is the managed-usage billing unit: **100 credits = $1.00** (`1` credit = `$0.01`).
Two operations are metered, each as a flat base credit plus the input-only embedding token
cost.
| Operation | Flat base credit | Plus | When it is charged |
| --- | :-: | --- | --- |
| **File ingest** | `1` per document | the document's embedding token cost (input-only), recorded by the ingest worker | Once per document, idempotent on the document ID. A retry of an unchanged document is **not** re-charged. |
| **Retrieval** | `1` per call | the query-embedding token cost (input-only), recorded on success | Once per `search`, `hybrid-search`, `retrieve-context`, or multi-knowledge-base search. |
A multi-knowledge-base search charges **one** retrieval base if **any** queried knowledge
base is managed, regardless of order. Creating, listing, or updating a knowledge base is
**not** credit-gated.
The embedding token cost uses the standard token-metering formula with input tokens only
(embeddings have no completion tokens): `cost = prompt_tokens · in_rate / 1e6 · MARGIN ·
SCALE`, where `MARGIN` is `1.05` (a 5% system margin) and `SCALE` is `100`. BYOK
providers run the same searches but record **no** credit cost. For the full credit model,
see [Credits & metering](/billing/credits); for what each plan allows, see
[Plans & pricing](/billing/plans).
## The billing gate (402 / 403 / 429)
Managed ingest and managed retrieval pass through the ModuleX billing admission gate
**before** any embedding runs. The gate fails closed: when your plan allowance or wallet is
exhausted, a quota is exceeded, or a rate limit is hit, it returns a flat `DenialEnvelope`
and **no document or search result is produced**.
The `DenialEnvelope` is a flat object — there is no `detail` wrapper — of the shape
`{code, layer, key, current, limit, reason}`:
The machine-readable denial reason, for example `credit_plan_exhausted`, `quota_exceeded`,
or `rate_limit_exceeded`.
The gate layer that denied the call. Maps to the HTTP status: `credit` → `402`, `wallet` →
`402`, `quota` → `403`, `rate` → `429`.
The denied resource key, for example the organization UUID or the rate class. May be
`null`.
The current usage at the time of denial. May be `null`.
The limit that was hit. May be `null`.
The denial reason, mirroring `code`.
```json 402 — plan credits exhausted
{
"code": "credit_plan_exhausted",
"layer": "credit",
"key": "",
"current": null,
"limit": 5000.0,
"reason": "credit_plan_exhausted"
}
```
```json 403 — quota exceeded
{
"code": "quota_exceeded",
"layer": "quota",
"key": "",
"current": null,
"limit": null,
"reason": "quota_exceeded"
}
```
```json 429 — rate limited
{
"code": "rate_limit_exceeded",
"layer": "rate",
"key": "api",
"current": 500,
"limit": 500,
"reason": "rate_limit_exceeded"
}
```
A `429` carries `Retry-After` (default `60`) and `X-RateLimit-Limit` / `X-RateLimit-Remaining`
/ `X-RateLimit-Reset` headers.
**Two different denial shapes coexist for managed knowledge.** The credit, wallet, quota,
and rate gate denials use the flat `DenialEnvelope` above. Document-level limits — a file
larger than your plan's `max_file_size_bytes`, exceeding the documents-per-knowledge-base
cap, or running out of storage quota — are raised as a `KnowledgeBaseQuotaExceededError` →
`403` with the **ordinary** `{detail}` shape, **not** the `DenialEnvelope`. Branch on both.
See [Usage gating & limits](/billing/usage-gating) and
[Errors & status codes](/api-reference/errors).
## Worked example — search a managed knowledge base
Every request authenticates with `Authorization: Bearer mx_live_…` plus the
`X-Organization-ID` header (see [Authentication](/api-reference/authentication)). Searching a
managed knowledge base reserves `1` retrieval credit before the query is embedded.
```bash cURL
curl -X POST https://api.modulex.dev/knowledge-bases/7c1e.../search \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: org_123" \
-H "Content-Type: application/json" \
-d '{"query":"how to install","top_k":5,"min_score":0.3}'
```
```python Python
import asyncio
from modulex import Modulex
mx = Modulex(api_key="mx_live_xxx", organization_id="org_123")
async def main():
result = await mx.knowledge_bases.search(
"7c1e...",
query="how to install",
top_k=5,
min_score=0.3,
)
print(result)
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const mx = new Modulex({
apiKey: "mx_live_xxx",
organizationId: "org_123",
});
const result = await mx.knowledgeBases.search("7c1e...", {
query: "how to install",
topK: 5,
minScore: 0.3,
});
console.log(result);
```
The SDK method names and parameter casing for the knowledge-base search operation are not
fully pinned in the research base. The cURL request and its body are verified against the
backend; the Python and JavaScript snippets above show the standard ModuleX client shape and
should be confirmed against the [JavaScript SDK](/sdks/javascript) and
[Python SDK](/sdks/python) references before relying on the exact method names. {/* TODO: confirm knowledge-base search SDK method names/casing against modulex-js and modulex-python */}
A successful response returns the matching chunks with cosine-similarity scores. The full
request and response schema for every managed knowledge operation — search, hybrid search,
retrieve-context, multi-knowledge-base search, ingest, and document management — lives in
[Managed knowledge (modulexdb)](/platform/knowledge/managed).
## Limits
These document limits apply to every knowledge base, managed or BYOK.
| Limit | Value |
| --- | --- |
| Supported file types | `pdf`, `docx`, `doc`, `txt`, `md`, `html`, `csv`, `json`, `xlsx`, `pptx` |
| Documents per knowledge base | `500` |
| Per-file size cap | Your plan's `max_file_size_bytes` (Free 10 MB, Pro 50 MB, Max 100 MB, Enterprise unlimited) |
| Total org storage | Your plan's storage entitlement (Free 1 GiB, Pro 50 GiB, Max 500 GiB, Enterprise unlimited) |
**The per-file cap is a plan entitlement, not a fixed 50 MB.** The
`/knowledge-bases/info/supported-file-types` endpoint advertises 50 MB as a fallback, but
the enforced cap is your plan value. See [Managing documents](/platform/knowledge/documents).
## Related pages
The full technical reference: embedding and chunking schema, ingest and retrieval
pipelines, and the per-operation REST surface.
Compare modulexdb with the BYOK vector stores.
Retrieve from modulexdb inside a workflow.
What a credit is and exactly what managed knowledge consumes.
---
# MongoDB Atlas Vector Search
URL: https://docs.modulex.dev/integrations/knowledge-providers/mongodb-atlas
Connect MongoDB Atlas Vector Search to ModuleX as a bring-your-own-key knowledge provider: create the credential from a connection string, configure a workflow knowledge node against a database.collection, and run uncosted $vectorSearch retrieval. Every field, type, default, and error.
MongoDB Atlas Vector Search is a **bring-your-own-key (BYOK) knowledge provider** for
ModuleX. You connect your own Atlas cluster with a connection string, and ModuleX runs
semantic retrieval against an existing collection that already holds vector embeddings —
ModuleX does not host or ingest the vectors. The provider name on the wire is
`mongodb_atlas`.
It is one of the [knowledge providers](/integrations/knowledge-providers/overview) ModuleX
can retrieve from. Unlike the managed store
[modulexdb](/integrations/knowledge-providers/modulexdb) — where ModuleX hosts the vectors,
runs the embeddings, and meters the work in [credits](/billing/credits) — MongoDB Atlas is
**BYOK and uncosted**: retrieval runs against your cluster and is **never credited** by
ModuleX. Your upstream Atlas and embedding-provider usage is billed by those providers
directly. The other BYOK stores are
[Qdrant](/integrations/knowledge-providers/qdrant),
[Pinecone](/integrations/knowledge-providers/pinecone), and
[Weaviate](/integrations/knowledge-providers/weaviate).
This page is the **provider-catalog entry** for `mongodb_atlas`: how to connect your cluster,
how to configure a [workflow knowledge node](/workflow-builder/nodes/knowledge) to retrieve
from it, and the exact request and result shapes. For the broader managed-vs-BYOK model and
the RAG concept, see [Knowledge & RAG](/concepts/knowledge-rag) and
[External knowledge providers](/platform/knowledge/external-providers).
## What Atlas does in ModuleX
MongoDB Atlas is a **retrieval-only** provider in ModuleX. ModuleX queries your cluster's
existing vector index; it does not upload documents, create indexes, or chunk and embed
content for you. You are responsible for populating the collection with documents that
contain an embedding field and for creating an Atlas Vector Search index over that field.
Because Atlas requires a precomputed query vector for similarity search, ModuleX embeds the
search text first (using an embedding credential you configure) and then runs Atlas's
`$vectorSearch` aggregation. Two surfaces use the provider:
A [knowledge node](/workflow-builder/nodes/knowledge) with `provider_type` set to
`mongodb_atlas` retrieves matching documents inside a running workflow and feeds them to
a downstream LLM or agent node. This is the primary BYOK retrieval path.
Atlas appears in the [integration catalog](/integrations/catalog) as a
`knowledge_provider` with `query`, `list_databases`, and `list_collections` actions and
a connection-string credential. The catalog is the browse and credential-setup surface.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4150 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** BYOK retrieval flow from a ModuleX knowledge node to MongoDB Atlas Vector Search.
**[IMAGE_DETAILS]:** Left-to-right flow. Box 1 "Knowledge node (provider_type: mongodb_atlas)". Arrow to Box 2 "ModuleX embeds the query text via embedding_config (e.g. OpenAI)". Arrow to Box 3 "Atlas $vectorSearch on database.collection". Arrow back to Box 4 "matches: id, score, content, metadata". A small lock icon labeled "connection string credential" sits over the arrow into Atlas, and a side note reads "BYOK — not credited by ModuleX". Light theme, 16:9, brand palette.
## Connect MongoDB Atlas
You connect Atlas by storing a credential that holds your cluster connection string. The
credential is created against the `mongodb_atlas` integration with `auth_type` set to
`custom`. You can create it in the app or over the API.
### Credential fields
The Atlas auth schema has a single field.
Your MongoDB Atlas connection string, in `mongodb+srv://...` form (for example
`mongodb+srv://user:password@cluster.mongodb.net/`). This value is **sensitive** — it is
encrypted at rest and never returned in full by the API. ModuleX uses it to open an async
client (`motor`) against your cluster for every retrieval. The connecting database user
needs read access to the database and collection you intend to query.
The connection string embeds your cluster credentials. Scope the Atlas database user to the
data ModuleX needs to read, and rotate the credential if the string is exposed. ModuleX
encrypts stored credential data; see [Data security & encryption](/security/data-encryption).
### Connect in the app
Connecting a knowledge provider is an org-level write, so it requires the **owner** or
**admin** role (see [Roles & permissions](/security/roles-permissions); the `member` role is
retired). In the org settings, open the integration catalog, select **MongoDB Atlas Vector
Search**, choose **Add credential**, paste the connection string, and save. ModuleX validates
the credential by connecting and listing databases before it is stored.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4151 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The Add-credential dialog for MongoDB Atlas Vector Search.
**[SCREENSHOT_DETAILS]:** ModuleX org settings, integration catalog, MongoDB Atlas detail open with the "Add credential" dialog showing the single "Connection String" field (masked sample `mongodb+srv://user:password@cluster.mongodb.net/`), a display-name field, a "Set as default" toggle, and a "Test" button. Light theme, desktop width, no real secrets visible.
### Connect over the API
Every request authenticates with `Authorization: Bearer mx_live_…` plus the
`X-Organization-ID` header (the backend also accepts `X-API-KEY`); see
[Authentication](/api-reference/authentication). Creating a credential requires the
owner/admin role.
Send `auth_type: "custom"` and put the connection string in `auth_data` keyed by the field
name `connection_string`. A successful create returns `201` with a `CredentialResponse`; keep
the returned `credential_id` — the knowledge node references it.
```bash cURL
curl -X POST https://api.modulex.dev/credentials \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: org_123" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "mongodb_atlas",
"auth_type": "custom",
"auth_data": {
"connection_string": "mongodb+srv://user:password@cluster.mongodb.net/"
},
"display_name": "Atlas production",
"make_default": true
}'
```
```python Python
import asyncio
from modulex import Modulex
mx = Modulex(api_key="mx_live_xxx", organization_id="org_123")
async def main():
credential = await mx.credentials.create(
integration_name="mongodb_atlas",
auth_type="custom",
auth_data={
"connection_string": "mongodb+srv://user:password@cluster.mongodb.net/",
},
display_name="Atlas production",
make_default=True,
)
print(credential["credential_id"])
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const mx = new Modulex({
apiKey: "mx_live_xxx",
organizationId: "org_123",
});
const credential = await mx.credentials.create({
integrationName: "mongodb_atlas",
authType: "custom",
authData: {
connection_string: "mongodb+srv://user:password@cluster.mongodb.net/",
},
displayName: "Atlas production",
makeDefault: true,
});
console.log(credential.credential_id);
```
The `POST /credentials` request body and the `custom` auth type are verified against the
backend. The exact SDK method names and parameter casing for credential creation are not
fully pinned in the research base; confirm them against the
[JavaScript SDK](/sdks/javascript) and [Python SDK](/sdks/python) references before relying
on the snippet shapes. {/* TODO: confirm credentials.create SDK method names/casing against modulex-js and modulex-python */}
### Credential response
`POST /credentials` returns a `CredentialResponse`. The connection string is never echoed
back.
The credential identifier. Pass this as the knowledge node's `credential_id`.
`mongodb_atlas`.
`knowledge_provider`.
The display name you supplied, or a generated default.
`custom`.
Whether this is the default credential for `mongodb_atlas` in the organization.
Creation timestamp.
Last-update timestamp.
When the credential was last used for a retrieval. `null` until first use.
Expiry, if any. Connection-string credentials do not expire on their own.
Any metadata you attached at create time.
### Test the connection before saving
To validate a connection string without persisting it, call `POST /credentials/test-temporary`
with the same `integration_name`, `auth_type`, and `auth_data`. For Atlas, the test connects
to the cluster, pings the server, and lists databases; it has no HTTP test endpoint.
```bash cURL
curl -X POST https://api.modulex.dev/credentials/test-temporary \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: org_123" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "mongodb_atlas",
"auth_type": "custom",
"auth_data": {
"connection_string": "mongodb+srv://user:password@cluster.mongodb.net/"
}
}'
```
The response is a `TestTemporaryCredentialResponse` with `is_valid`, a human-readable
`message`, `tested_at`, `test_method`, `integration_name`, and `auth_type`. A failed
connection reports `is_valid: false` with the reason in `message`.
## Catalog actions
In the [integration catalog](/integrations/catalog), `mongodb_atlas` is a
`knowledge_provider` that advertises three actions. These describe the provider's capability
in the catalog; retrieval inside a workflow is driven by the
[knowledge node](/workflow-builder/nodes/knowledge) config in the next section, which maps
onto the `query` action.
Performs vector similarity search using MongoDB Atlas `$vectorSearch`.
Database name.
Collection name.
The Atlas Vector Search index name.
The query embedding vector.
The field path that holds the stored vectors.
Number of candidates Atlas considers before returning results.
Maximum number of results to return.
Pre-filter conditions in MongoDB query-language (MQL) form.
Returns an array of objects, each `{_id, score, document}`.
Takes no parameters. Returns an array of `{name, sizeOnDisk}` objects.
Database name.
Returns an array of collection-name strings.
## Configure BYOK retrieval in a knowledge node
A [knowledge node](/workflow-builder/nodes/knowledge) retrieves from a provider inside a
running workflow. To retrieve from Atlas, set the node's `provider_type` to `mongodb_atlas`,
point `credential_id` at your Atlas credential, set `collection_name` to a
`database.collection` value, and supply an `embedding_config` so ModuleX can embed the query.
### How retrieval runs
When the node executes, ModuleX:
It loads the org credential by `credential_id`, decrypts the stored connection string,
and opens an async Atlas client.
Atlas requires a precomputed query vector, so ModuleX embeds the resolved `query` text
using `embedding_config`. If `embedding_config` is missing, the node fails with a
validation error.
It splits `collection_name` on the first `.` into database and collection, then runs an
aggregation: a `$vectorSearch` stage followed by `$addFields` that exposes the
`vectorSearchScore` as `score`. The vector field is excluded from results unless vectors
are requested.
Matches scoring below `min_score` are dropped. Each remaining document becomes a chunk
with `content`, `score`, `metadata`, and `id`, then the node formats them per
`output_format`.
**BYOK retrieval is uncosted.** Unlike [modulexdb](/integrations/knowledge-providers/modulexdb),
an Atlas knowledge node consumes **no ModuleX credits** — there is no billing gate on the
retrieval. Your Atlas query cost and your embedding-provider token cost are billed by those
providers directly. See [Credits & metering](/billing/credits).
### Knowledge-node fields
These are the `KnowledgeNodeConfig` fields that apply when `provider_type` is `mongodb_atlas`.
Set to `mongodb_atlas` to retrieve from Atlas. One of `modulexdb`, `qdrant`, `pinecone`,
`weaviate`, `mongodb_atlas`.
The Atlas credential ID from the credential you created. ModuleX decrypts its connection
string to reach your cluster.
The target collection in **`database.collection`** format (for example
`support.kb_chunks`). It must contain the first `.` separator; a value with no `.` fails
with a `database.collection format` error. Required for Atlas — a node with no
`collection_name` fails before it queries.
The search text. Supports `{{nodeId.path}}` references so the query can come from an
upstream node's output. ModuleX embeds this text to build the Atlas query vector.
When `true`, the workflow input is used as the query instead of the `query` field.
**Required** for Atlas. The embedding model ModuleX uses to embed the query text before the
vector search. The embedding model and dimension you configure here must match the model
and dimension used to build the vectors stored in your Atlas collection, or scores will be
meaningless. See the sub-fields below.
Number of results to retrieve. Range `1`–`50`.
Minimum similarity score threshold. Range `0.0`–`1.0`. Matches from Atlas scoring below
this value are dropped.
Maximum tokens in the formatted context string, when `output_format` returns a context.
Range `100`–`10000`.
Provider-specific pre-filter passed through to Atlas as the `$vectorSearch` filter (MQL
form). `null` by default.
**Not used** for Atlas (it applies to Pinecone-style providers). Leave unset.
Filter to specific document IDs. **Native (modulexdb) knowledge bases only** — has no
effect on Atlas. Use `filters` for Atlas pre-filtering.
How the node returns results. One of `chunks` (individual matches with metadata), `context`
(a single formatted RAG string), or `both`.
Include each document's metadata (every field except `_id`, `score`, and the vector field)
in the results.
Include source-document info in the formatted context string.
The integration that owns the embedding provider, for example `openai` or `cohere`.
The provider identifier, for example `openai`.
The embedding model, for example `text-embedding-3-small`. Match this to the model that
produced the vectors stored in your Atlas collection.
The credential for the embedding provider. If omitted, ModuleX uses the organization's
default credential for `integration_name`.
### Atlas index defaults
ModuleX builds the `$vectorSearch` stage with these defaults. Make sure your Atlas Vector
Search index and stored documents match them, or override the index in your collection
setup accordingly.
| Setting | Default ModuleX uses | Notes |
| --- | --- | --- |
| Vector Search index name | `vector_index` | The index name passed to `$vectorSearch`. Create your Atlas index with this name. |
| Vector field path | `embedding` | The document field that holds the stored vectors. |
| `numCandidates` | `top_k × 10` | Candidate pool size; scales with `top_k`. |
| `limit` | `top_k` | Results returned by the aggregation. |
ModuleX queries Atlas with a fixed index name of `vector_index` and a fixed vector field of
`embedding` for the knowledge-node retrieval path. Your collection must have an Atlas Vector
Search index named `vector_index` over a field named `embedding`. {/* TODO: confirm whether index_name/vector_field are surfaced as overridable node-config fields in the UI; the workflow-engine call uses the adapter defaults */}
### Example node config
```json
{
"provider_type": "mongodb_atlas",
"credential_id": "939f74dc-7b2f-473c-b87d-b95c30c32fd3",
"collection_name": "support.kb_chunks",
"query": "{{trigger.question}}",
"top_k": 5,
"min_score": 0.3,
"output_format": "context",
"embedding_config": {
"integration_name": "openai",
"provider_id": "openai",
"model_id": "text-embedding-3-small"
}
}
```
## Retrieval results
Each Atlas match is normalized into a chunk before the node formats it.
The matched document's `_id`, stringified.
The Atlas `vectorSearchScore` for the match. Matches below `min_score` are excluded.
The text content extracted from the document. ModuleX looks for a text value in common
fields — `content`, `text`, `chunk_text`, `page_content`, `data`, `body`, `summary`,
`document` — and returns the first match, or `null` if none is present.
Every document field except `_id`, `score`, and the vector field. Present only when
`include_metadata` is `true`.
The node then returns `chunks`, a formatted `context` string, or `both`, per
`output_format`. The downstream LLM or agent node consumes this as RAG context.
## Errors
Atlas retrieval runs inside the workflow executor, so failures surface as the node failing
the run rather than as an HTTP envelope. Because BYOK retrieval is uncosted, there is **no**
`DenialEnvelope` (`{code, layer, …}`) on this path — that envelope only appears on managed
(`modulexdb`) knowledge operations. The credential-management endpoints return the standard
`{detail}` `HTTPException` shape. See [Errors & status codes](/api-reference/errors).
| Condition | What you see |
| --- | --- |
| `collection_name` missing | The node fails with `collection_name is required for external provider`. |
| `collection_name` has no `.` | `Collection name must be in 'database.collection' format`. |
| `embedding_config` missing | `embedding_config required for providers that don't handle embeddings`. |
| No query vector reached Atlas | `MongoDB Atlas requires query_vector for search`. |
| Bad or unauthorized connection string | `MongoDB authentication failed: …` (an authentication error). |
| Cluster unreachable / `motor` not installed | `Failed to connect to MongoDB: …` (a connection error). |
| Aggregation failure (for example a missing or misnamed Atlas index) | `MongoDB query failed: …` (a query error). |
| Credential not found in the org | `Credential not found: `. |
The `motor` driver must be available in the runtime for Atlas connections. If it is missing,
connections fail with an instruction to install it. This is an environment dependency of the
ModuleX backend, not something you configure per credential.
## Related pages
Compare MongoDB Atlas with modulexdb and the other BYOK vector stores.
The managed alternative: ModuleX hosts the vectors and meters usage in credits.
Retrieve from Atlas inside a workflow.
The product overview of bringing your own vector store.
How ModuleX stores and resolves integration credentials.
The retrieval-augmented-generation model behind knowledge nodes.
---
# Knowledge providers: managed and external vector stores
URL: https://docs.modulex.dev/integrations/knowledge-providers/overview
The vector stores ModuleX retrieves from for RAG: the managed modulexdb store versus bring-your-own Qdrant, Pinecone, MongoDB Atlas, and Weaviate, with the exact connection fields, the knowledge node contract, and how retrieval is billed.
A knowledge provider is the vector store ModuleX searches when a workflow or chat
needs retrieval. ModuleX supports two families: the **managed store**
(`modulexdb`), where ModuleX hosts your embeddings and chunks and bills retrieval
in credits, and **external (bring-your-own) stores** — Qdrant, Pinecone, MongoDB
Atlas, and Weaviate — that you connect with your own credentials and query
without ModuleX markup. This page is the exhaustive reference for both: how each
is identified, the exact fields you supply to connect, the knowledge node
contract that consumes them, and the retrieval billing model.
For the conceptual model of retrieval-augmented generation in ModuleX, see
[Knowledge & RAG](/concepts/knowledge-rag). To create and manage a managed
knowledge base in the app, see [Knowledge overview](/platform/knowledge/overview)
and [Managed knowledge (modulexdb)](/platform/knowledge/managed). To wire a
provider into a graph, see the [Knowledge node](/workflow-builder/nodes/knowledge).
Knowledge bases and their provider credentials are **organization-scoped**. Every
knowledge endpoint and every credential operation requires the **owner** or
**admin** role (`organization_admin_required`); the `member` role is retired. The
organization is selected by the `X-Organization-ID` header on every request — see
[Org context & X-Organization-ID](/security/org-context).
## The two provider families
A provider is identified on the wire by a `provider_type` value. The backend
enumerates exactly five (`KnowledgeProviderType`): one managed and four external.
| `provider_type` | Family | Display name | How you connect | Retrieval billing |
| --- | --- | --- | --- | --- |
| `modulexdb` | Managed | modulexdb (managed) | Auto-created when you create a knowledge base | Billed in credits |
| `qdrant` | External (BYOK) | Qdrant | `custom` credential (URL + API key) | Uncosted |
| `pinecone` | External (BYOK) | Pinecone | `custom` credential (API key + environment) | Uncosted |
| `mongodb_atlas` | External (BYOK) | MongoDB Atlas Vector Search | `custom` credential (connection string) | Uncosted |
| `weaviate` | External (BYOK) | Weaviate | `custom` credential (URL + API key) | Uncosted |
This page is the cross-provider reference. For the field-by-field connect steps,
open the page for your store: [modulexdb (managed)](/integrations/knowledge-providers/modulexdb),
[Qdrant](/integrations/knowledge-providers/qdrant),
[Pinecone](/integrations/knowledge-providers/pinecone),
[MongoDB Atlas](/integrations/knowledge-providers/mongodb-atlas), and
[Weaviate](/integrations/knowledge-providers/weaviate).
### Managed: modulexdb
The managed store is the default. When you create a knowledge base without
choosing an external provider, ModuleX provisions a `modulexdb` knowledge base: it
parses, chunks, and embeds your documents, stores the chunk vectors in its own
pgvector-backed store, and serves vector, hybrid, and RAG-context search over
them. You do not connect anything — the store is created for you, and an internal
credential is linked to the knowledge base automatically (the "native knowledge
base = credential" pattern).
A knowledge base counts as **managed** when its `embedding_config.integration_name`
is `modulexai`. Managed retrieval and managed ingest are metered in credits (see
[Retrieval billing](#retrieval-billing) below). Choose modulexdb when you want
ModuleX to own ingestion and storage end to end and you do not already run a vector
database.
### External: bring your own vector store
An external provider connects ModuleX to a vector database you already operate.
ModuleX does **not** ingest or store documents for an external provider — you
populate and maintain your own collection/index, and ModuleX only **queries** it
at run time. Because ModuleX provides no storage and no embeddings for these,
external retrieval is **uncosted** (your vector-database vendor and your embedding
provider bill you directly — this is bring-your-own-key usage; see
[BYOK in the glossary](/reference/glossary)).
All four external providers connect with a `custom` auth credential. Each declares
its own connection fields and exposes catalog actions (`query`, plus a list/describe
pair) so the catalog UI can show what the provider can do. Choose an external
provider when you already have vectors in Qdrant, Pinecone, MongoDB Atlas, or
Weaviate and want to retrieve over them without re-ingesting into ModuleX.
**Important capability boundary.** External providers query an existing
collection; they have no ModuleX-side ingestion pipeline. The document
upload, chunking, embedding, and processing flows described in
[Managing documents](/platform/knowledge/documents) apply to **managed** knowledge
bases only. You are responsible for keeping an external collection populated and
its embedding model consistent with the one you configure on the ModuleX side.
## How a provider is connected
The connection mechanism differs by family.
Create a knowledge base — in the app under Knowledge, or with `POST /knowledge-bases`.
ModuleX provisions the managed store, auto-discovers an embedding-capable
credential if you do not supply one, and links an internal `modulexdb` credential
to the new knowledge base. There is nothing else to connect. See
[Build a RAG knowledge base](/guides/build-a-knowledge-base).
Create a `custom` credential for the provider with its connection fields (URL,
API key, connection string — see the per-provider tables below), in the app under
Settings → Credentials, or with `POST /credentials`. ModuleX encrypts the secret
at rest and tests the connection before saving where a test endpoint is declared.
See [Managing credentials](/integrations/managing-credentials).
In a workflow, add a [Knowledge node](/workflow-builder/nodes/knowledge), set its
`provider_type`, and point `credential_id` at the credential (or, for managed, the
auto-linked knowledge-base credential). For external providers, also set
`collection_name` and an `embedding_config`. The node configuration is documented
in [The knowledge node contract](#the-knowledge-node-contract) below.
### Creating an external-provider credential
External providers use the `custom` auth schema. Create the credential with the
provider's `name` and an `auth_data` object holding its fields. Auth in every
request follows the standard model: `Authorization: Bearer mx_live_…` plus
`X-Organization-ID`.
```bash cURL
curl -X POST https://api.modulex.dev/credentials \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: org_123" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "qdrant",
"auth_type": "custom",
"display_name": "Prod Qdrant",
"make_default": true,
"auth_data": {
"url": "https://xyz-abc.aws.cloud.qdrant.io:6333",
"api_key": "qdrant-api-key-..."
}
}'
```
```python Python
from modulex import ModuleX
client = ModuleX(api_key="mx_live_xxx", organization_id="org_123")
credential = client.credentials.create(
integration_name="qdrant",
auth_type="custom",
display_name="Prod Qdrant",
make_default=True,
auth_data={
"url": "https://xyz-abc.aws.cloud.qdrant.io:6333",
"api_key": "qdrant-api-key-...",
},
)
```
```javascript JavaScript
import { ModuleX } from "modulex";
const client = new ModuleX({
apiKey: "mx_live_xxx",
organizationId: "org_123",
});
const credential = await client.credentials.create({
integration_name: "qdrant",
auth_type: "custom",
display_name: "Prod Qdrant",
make_default: true,
auth_data: {
url: "https://xyz-abc.aws.cloud.qdrant.io:6333",
api_key: "qdrant-api-key-...",
},
});
```
The exact SDK method surface for credential creation may vary between the
JavaScript and Python SDKs; the credential resource is not guaranteed to be at
parity across both. Confirm against the [SDK ⇄ API parity matrix](/sdks/parity)
and fall back to the REST call above when a method is absent. The cURL request is
the authoritative shape.
## Connection fields by provider
Each external provider declares its connection fields in its manifest under a
`custom` auth schema. The fields below are the exact `auth_data` keys you supply.
URL of your Qdrant instance, including the port. Not treated as a secret.
Example: `https://xyz-abc.aws.cloud.qdrant.io:6333`.
API key for Qdrant Cloud. Optional for local/unauthenticated instances. Stored
encrypted. Example format: `qdrant-api-key-...`.
ModuleX validates the connection by listing collections
(`GET {url}/collections`, expecting a `result` field in the response). Catalog
actions: `query`, `list_collections`, `get_collection_info`.
Your Pinecone API key. Stored encrypted. Example format: `pcsk_...`.
Pinecone environment. Not treated as a secret. Examples: `us-east-1-aws`,
`gcp-starter`.
ModuleX validates the connection by listing indexes
(`GET https://api.pinecone.io/indexes`, expecting an `indexes` field). Catalog
actions: `query`, `list_indexes`, `describe_index`. Pinecone queries accept an
optional `namespace`.
MongoDB Atlas connection string. Stored encrypted (it embeds your credentials).
Format: `mongodb+srv://user:password@cluster.mongodb.net/`.
ModuleX validates by listing databases. Catalog actions: `query`,
`list_databases`, `list_collections`. A query targets a `database`, `collection`,
vector-search `index_name`, and the `path` field that holds the vectors.
URL of your Weaviate instance. Not treated as a secret. Example:
`https://your-cluster.weaviate.cloud`.
API key for Weaviate Cloud. Optional for local/unauthenticated instances. Stored
encrypted. Example format: `weaviate-api-key-...`.
ModuleX validates by checking cluster status. Catalog actions: `query`,
`list_classes`, `get_class_stats`. Weaviate is the one provider that can search
from text directly (`nearText`) when a `text2vec` module is enabled, so a query
embedding may be optional; otherwise supply a `query_vector`.
The connection fields above arrive in each manifest under a `fields` array, not the
`setup_environment_variables` array used by tool and LLM-provider auth schemas. If
you read the raw manifest from the catalog API, expect `fields` for the four
knowledge providers. The manifest's `provider_type` value (`external`) is dropped
during catalog sync and never appears in API responses — do not rely on it.
## Browsing providers in the catalog
The catalog exposes knowledge providers as read-only metadata for discovery; it is
not the execution surface. List providers with `GET /integrations/knowledge-providers`
or fetch one with `GET /integrations/knowledge-providers/{provider_name}`. Both
require the owner or admin role and `X-Organization-ID`. The detail endpoint
returns the provider's `actions` and its `auth_schemas` (with OAuth flags enriched
where applicable — not relevant to these `custom`-auth providers).
```bash cURL
curl 'https://api.modulex.dev/integrations/knowledge-providers' \
-H 'Authorization: Bearer mx_live_xxx' \
-H 'X-Organization-ID: org_123'
```
```python Python
from modulex import ModuleX
client = ModuleX(api_key="mx_live_xxx", organization_id="org_123")
providers = client.integrations.list(type="knowledge_provider")
```
```javascript JavaScript
import { ModuleX } from "modulex";
const client = new ModuleX({ apiKey: "mx_live_xxx", organizationId: "org_123" });
const providers = await client.integrations.list({ type: "knowledge_provider" });
```
Unique provider id, e.g. `qdrant`, `pinecone`, `mongodb_atlas`, `weaviate`.
Human-readable name, e.g. `MongoDB Atlas Vector Search`.
Short summary of the provider.
Always `knowledge_provider` for these entries.
Tags such as `Vector Database`, `semantic-search`.
The provider's catalog actions (returned by the detail endpoint), each with
`name`, `description`, `parameters`, and a derived `output_schema`.
Action id, e.g. `query`, `list_indexes`.
What the action does.
Map of parameter name to `{type, description, required, default}`.
JSON-schema description of the action's result shape.
The auth variants the provider supports. For all four external providers this is a
single `custom` schema whose connection fields live under `fields` (see the
warning above).
The catalog SDK method names and exact filter arguments may differ between SDKs and
are not guaranteed to be at parity. Treat the cURL request as authoritative; verify
SDK signatures against the [SDK ⇄ API parity matrix](/sdks/parity).
## The knowledge node contract
A [Knowledge node](/workflow-builder/nodes/knowledge) is how a provider is consumed
inside a workflow. The node configuration (`KnowledgeNodeConfig`) is shared across
families; a handful of fields apply only to external providers.
Credential for the knowledge base. For managed, this is the internal credential
auto-linked to the knowledge base; for external, the `custom` credential you
created for the provider.
One of `modulexdb`, `qdrant`, `pinecone`, `weaviate`, `mongodb_atlas`.
The search query. Supports `{{nodeId.path}}` references to upstream node outputs
for dynamic queries.
When `true`, use the workflow input as the query instead of the `query` field.
Collection/index/class name on the external store. **Required for external
providers**; ignored by modulexdb.
Namespace for Pinecone (or similar). External only.
Number of results to retrieve. Range 1–50.
Minimum similarity-score threshold, 0.0–1.0. Score scales are normalized per
provider, so the effective floor differs by vector store.
Maximum tokens in the formatted context string (for the `context` output format).
Range 100–10000.
Provider-specific filter conditions applied to the search.
Restrict retrieval to specific document ids. **Managed knowledge bases only.**
One of `chunks` (individual chunks with metadata), `context` (a single formatted
RAG context string), or `both`.
Include chunk metadata in results.
Include source-document info in the formatted context.
Embedding settings for providers that do not embed internally. **Required for
external vector databases** (Qdrant, Pinecone, MongoDB Atlas, and Weaviate when not
using a text vectorizer), because ModuleX must turn the query text into a vector
before searching your store.
Embedding provider integration, e.g. `openai`, `cohere`.
Provider identifier, e.g. `openai`.
Embedding model id, e.g. `text-embedding-3-small`.
Credential for the embedding provider. If omitted, the organization's default
credential for that integration is used.
Match the embedding model in `embedding_config` to the model your external
collection was indexed with. ModuleX embeds the query with the model you configure;
if it differs from the one used to build the collection (or the dimension does not
match), similarity scores are meaningless and retrieval returns poor or empty
results. For managed (modulexdb) knowledge bases this is handled for you — ingest
and query use the same configured embedding model.
**Known limitation.** External-provider retrieval is implemented in the workflow
engine's knowledge node, which embeds the query (per `embedding_config`) and calls
the provider adapter. A separate, secondary executor helper path does **not** yet
support external providers and returns "External provider not yet supported" if it
is reached. If an external-provider knowledge node returns that error, treat it as a
known gap; see [Known limitations](/reference/known-limitations). Managed
(modulexdb) retrieval is supported on every path.
## Retrieval billing
Whether a provider is metered depends entirely on the family.
| Operation | Managed (modulexdb) | External (BYOK) |
| --- | --- | --- |
| Document ingest (parse → chunk → embed) | `FILE_INGEST_BASE = 1` credit, plus per-chunk embedding token cost | Not applicable — you ingest into your own store |
| Retrieval (search / hybrid / retrieve-context) | `RETRIEVAL_BASE = 1` credit, plus query-embedding token cost | Uncosted by ModuleX |
A knowledge base is billed only when it is managed — that is, when
`embedding_config.integration_name == "modulexai"`. One credit equals $0.01.
External (BYOK) retrieval is not credited; your vector-database vendor and your
embedding provider bill you directly. For the full credit model see
[Credits & metering](/billing/credits).
On the interactive knowledge API, a managed-store credit or rate denial returns the
flat billing `DenialEnvelope` as **402 / 403 / 429** (reject-before-write — no
search runs). Inside a workflow run, the managed-retrieval gate is best-effort so a
billing hiccup never crashes an in-flight run. The error envelope shapes are
documented on [Errors & status codes](/api-reference/errors); the gate itself on
[Usage gating & limits](/billing/usage-gating).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4110 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** Decision diagram contrasting the managed modulexdb path with the external BYOK path.
**[IMAGE_DETAILS]:** Two side-by-side lanes. Left lane "Managed (modulexdb)": documents -> ModuleX ingest (parse/chunk/embed) -> pgvector store -> retrieval, with a credit-coin icon on ingest and retrieval. Right lane "External (BYOK)": your own collection in Qdrant/Pinecone/Atlas/Weaviate -> ModuleX embeds query -> adapter query -> results, marked "uncosted by ModuleX". Light and dark variants; 16:9; label the wire identifiers modulexdb / qdrant / pinecone / mongodb_atlas / weaviate.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4111 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The credential-add dialog connecting an external knowledge provider.
**[SCREENSHOT_DETAILS]:** Capture Settings -> Credentials -> Add credential with a knowledge provider (e.g. Qdrant) selected, showing the custom connection fields (URL, API key) and the test-before-save state. Dark theme; crop to the dialog; redact any real secret values.
## Next steps
Set up ModuleX-hosted storage and retrieval, billed in credits.
Bring your own Qdrant, Pinecone, MongoDB Atlas, or Weaviate.
Wire a provider into a workflow and shape its output.
End to end: create a knowledge base, ingest documents, and query it.
---
# Pinecone vector store (BYOK)
URL: https://docs.modulex.dev/integrations/knowledge-providers/pinecone
Connect Pinecone as a bring-your-own vector store in ModuleX: store an API key credential, configure a knowledge node, and run BYOK vector retrieval inside workflows.
Pinecone is a managed vector database you can bring to ModuleX as an external [knowledge provider](/integrations/knowledge-providers/overview). When you connect Pinecone, ModuleX queries **your** Pinecone index at retrieval time using a stored credential — your vectors stay in your Pinecone project, and Pinecone bills you directly. This is the **bring-your-own-key (BYOK)** model: unlike [managed knowledge (modulexdb)](/integrations/knowledge-providers/modulexdb), BYOK retrieval through Pinecone is **not** metered in ModuleX credits.
Use this page to store a Pinecone credential, configure a [knowledge node](/workflow-builder/nodes/knowledge) to point at your index, and understand exactly how ModuleX issues the query.
Pinecone is a **retrieval-only** provider in ModuleX. ModuleX queries an index you already populated; it does **not** upload, chunk, embed, or ingest documents into Pinecone for you. Document ingest (parse, chunk, embed) only applies to [managed knowledge bases](/platform/knowledge/managed). For Pinecone you own the indexing pipeline.
## How BYOK retrieval works
At a high level, a Pinecone-backed retrieval inside a workflow runs in five steps:
The [knowledge node](/workflow-builder/nodes/knowledge) reads its `credential_id`, loads the matching org credential, and decrypts the stored `auth_data` (your `api_key` and `environment`).
Pinecone stores vectors but does not embed text. ModuleX generates a query embedding first, using the node's `embedding_config` (for example OpenAI `text-embedding-3-small`). If `embedding_config` is missing, the node fails before any call to Pinecone.
ModuleX `POST`s the query vector to your Pinecone index endpoint with your `Api-Key` header, requesting `topK` matches in the configured `namespace`, with any metadata `filter` applied.
Each Pinecone match is mapped into a standard result with `id`, `score`, `content` (pulled from common metadata text fields), and `metadata`. Matches below `min_score` are dropped client-side.
Results are returned to the workflow as `chunks`, a formatted `context` string, or `both`, depending on the node's `output_format`.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4140 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** BYOK retrieval flow diagram for Pinecone.
**[IMAGE_DETAILS]:** Horizontal flow: workflow knowledge node to "embed query (embedding_config)" to ModuleX backend to your Pinecone index, then matches flowing back and being normalized to chunks/context. Label the embedding step "billed only if the embedding provider is managed" and the Pinecone call "BYOK, not metered in ModuleX credits". Light theme, 16:9, annotated.
## Before you start
You will need the following from your own Pinecone account:
- A **Pinecone API key**. Pinecone keys look like `pcsk_...`.
- The **environment** for your project (for example `us-east-1-aws` or `gcp-starter`).
- An existing, **populated index** whose vector dimension matches the embedding model you plan to use in ModuleX. A 1536-dimension index pairs with OpenAI `text-embedding-3-small`; mismatched dimensions cause Pinecone to reject the query.
- The index `namespace` you want to search, if you use namespaces.
You also need the **owner** or **admin** role in the ModuleX organization. Credential and knowledge routes require an admin/owner role; the retired `member` role cannot manage them. See [roles & permissions](/security/roles-permissions).
## Connect Pinecone
Connecting Pinecone means storing an encrypted credential in your organization. ModuleX persists it as a **custom** credential (`auth_type` is `custom`) under the `pinecone` integration, which the catalog classifies as a `knowledge_provider`.
### Credential fields
Pinecone declares a single `custom` auth schema with two fields:
Your Pinecone API key. Stored encrypted and never returned in plaintext. Sample format `pcsk_...`. This is the `Api-Key` header value ModuleX sends on every request to Pinecone.
Your Pinecone environment, for example `us-east-1-aws` or `gcp-starter`. ModuleX uses it to build the Pinecone host URL (see [Index URL resolution](#index-url-resolution)).
Optional, undocumented in the connect UI. If present in `auth_data`, this exact URL overrides the environment-derived index host. Set this when your index host does not match the legacy `environment`-based pattern — for example for serverless indexes. See [Index URL resolution](#index-url-resolution) for why this matters. {/* TODO: index_host is read by pinecone_adapter.py:59-60 but is not a declared manifest field; confirm whether the connect UI exposes it. */}
### Connect in the app
In the ModuleX app, go to the integrations area and select **Pinecone** under knowledge providers.
Paste your Pinecone **API key** and **environment**, give the credential a display name, and optionally mark it as the default for Pinecone.
ModuleX validates the credential by listing your indexes (`GET https://api.pinecone.io/indexes`). A `200` with an `indexes` field means the key works. This test is free.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4141 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The Pinecone connect form in the ModuleX app.
**[SCREENSHOT_DETAILS]:** Show the Pinecone knowledge-provider credential form with the API key field (masked, placeholder `pcsk_...`), the environment field (placeholder `us-east-1-aws`), a display-name field, and a "test connection" action. Capture the success state after testing. Light theme.
### Connect via the API
Create the credential with [`POST /credentials`](/api-reference/overview). The request body is read raw and the credential type is inferred from `integration_name`, `auth_type`, and `auth_data`. For Pinecone, send `auth_type: custom` with both fields nested under `auth_data`. ModuleX resolves `integration_type` to `knowledge_provider` from the catalog automatically.
All requests authenticate with `Authorization: Bearer mx_live_…` plus the `X-Organization-ID` header. See [authentication](/api-reference/authentication).
```bash cURL
curl -X POST https://api.modulex.dev/credentials \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: org_123" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "pinecone",
"auth_type": "custom",
"display_name": "Production Pinecone",
"make_default": true,
"auth_data": {
"api_key": "pcsk_xxx",
"environment": "us-east-1-aws"
}
}'
```
```python Python
import httpx
resp = httpx.post(
"https://api.modulex.dev/credentials",
headers={
"Authorization": "Bearer mx_live_xxx",
"X-Organization-ID": "org_123",
},
json={
"integration_name": "pinecone",
"auth_type": "custom",
"display_name": "Production Pinecone",
"make_default": True,
"auth_data": {
"api_key": "pcsk_xxx",
"environment": "us-east-1-aws",
},
},
)
resp.raise_for_status()
credential = resp.json()
print(credential["credential_id"])
```
```javascript JavaScript
const resp = await fetch("https://api.modulex.dev/credentials", {
method: "POST",
headers: {
Authorization: "Bearer mx_live_xxx",
"X-Organization-ID": "org_123",
"Content-Type": "application/json",
},
body: JSON.stringify({
integration_name: "pinecone",
auth_type: "custom",
display_name: "Production Pinecone",
make_default: true,
auth_data: {
api_key: "pcsk_xxx",
environment: "us-east-1-aws",
},
}),
});
if (!resp.ok) throw new Error(`Create credential failed: ${resp.status}`);
const credential = await resp.json();
console.log(credential.credential_id);
```
Creating, listing, and querying a Pinecone credential is a plain CRUD operation, so it returns the standard `{detail}` error envelope on failure (for example a `400` `"Invalid auth_data or auth_type…"` if the body is malformed). The flat billing `DenialEnvelope` does **not** apply here. See [errors & status codes](/api-reference/errors) for the full envelope reference. Pinecone credentials are stored with `auth_type` `custom`, so they appear in your credential list (only `internal` credentials are hidden).
#### Create-credential request fields
Must be `pinecone`. ModuleX looks this up in the integration catalog to resolve `integration_type` to `knowledge_provider`. An unknown name falls back to `tool`.
Must be `custom` for Pinecone. This routes the request to the custom-credential path, which stores arbitrary `auth_data` fields.
The Pinecone credential fields. Must not be empty. Carries `api_key` and `environment` (and optionally `index_host`).
A human-readable label for the credential. Defaults to `Pinecone Custom Credential` if omitted.
When `true`, sets this credential as the default for the `pinecone` integration, unsetting any prior default.
#### Test the saved credential
Validate a stored credential against Pinecone with `POST /credentials/{credential_id}/test`. ModuleX calls the integration's test endpoint — `GET https://api.pinecone.io/indexes` — and reports whether the key is valid.
```bash cURL
curl -X POST https://api.modulex.dev/credentials/cred_abc/test \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: org_123"
```
```python Python
import httpx
resp = httpx.post(
"https://api.modulex.dev/credentials/cred_abc/test",
headers={
"Authorization": "Bearer mx_live_xxx",
"X-Organization-ID": "org_123",
},
)
print(resp.json()["is_valid"])
```
```javascript JavaScript
const resp = await fetch(
"https://api.modulex.dev/credentials/cred_abc/test",
{
method: "POST",
headers: {
Authorization: "Bearer mx_live_xxx",
"X-Organization-ID": "org_123",
},
},
);
const result = await resp.json();
console.log(result.is_valid);
```
A successful test response has the shape `{credential_id, is_valid, message, tested_at}`.
## Configure a knowledge node
Once the credential exists, point a [knowledge node](/workflow-builder/nodes/knowledge) at your Pinecone index by setting `provider_type` to `pinecone` and supplying the index name, an embedding configuration, and the credential.
Because Pinecone stores only vectors, the knowledge node **requires** an `embedding_config` for Pinecone. ModuleX uses it to embed the query text before calling Pinecone. If `embedding_config` is omitted, the node raises a validation error and never reaches Pinecone.
### Knowledge node fields for Pinecone
The `credential_id` of your stored Pinecone credential.
Set to `pinecone`. Valid knowledge provider types are `modulexdb`, `qdrant`, `pinecone`, `weaviate`, and `mongodb_atlas`.
The Pinecone **index name** to search. ModuleX uses Pinecone's `index_name` terminology here as `collection_name`. Required for all external providers; the node fails with `"collection_name is required for external provider: pinecone"` if it is missing.
Embedding settings used to turn the query text into a vector. Required for Pinecone because Pinecone does not embed text. See [Embedding configuration](#embedding-configuration) for fields. Use a model whose output dimension matches your Pinecone index.
The search query. Supports `{{nodeId.path}}` references so the query can come from an earlier node's output.
When `true`, the workflow input is used as the query instead of the `query` field.
The Pinecone namespace to search within the index. Omit to search the default namespace.
Number of matches to return. Range 1–50. Sent to Pinecone as `topK`.
Minimum similarity score, 0.0–1.0. Pinecone has no native score threshold, so ModuleX drops matches below this value **after** Pinecone returns them. The score is Pinecone's raw match score for your index's metric; ModuleX does not re-normalize it.
A Pinecone metadata filter, passed through to Pinecone's query `filter` field verbatim. Use Pinecone filter syntax, for example `{"category": {"$eq": "docs"}}`.
Token budget for the formatted context string. Range 100–10000. Only applies when `output_format` is `context` or `both`.
How results are returned: `chunks` (individual matches with metadata), `context` (a single RAG-ready string), or `both`.
Include each match's metadata in the result. ModuleX requests `includeMetadata` from Pinecone accordingly.
Include source document headers in the formatted `context` output.
Filter to specific document IDs. **Native (modulexdb) KB only** — ignored for Pinecone. Use `filters` for Pinecone-side metadata filtering instead.
### Embedding configuration
The `embedding_config` object tells ModuleX which model to use when embedding the query. The model's output dimension must match your Pinecone index dimension.
The embedding provider integration, for example `openai` or `cohere`.
The provider identifier, for example `openai`.
The embedding model id, for example `text-embedding-3-small` (1536 dimensions) or `text-embedding-3-large` (3072 dimensions).
Credential for the embedding provider. If `null`, ModuleX uses your organization's default credential for that integration.
Dimension mismatch is the most common Pinecone failure. If your index was created at 1536 dimensions, the `embedding_config.model_id` must produce 1536-dimension vectors. A mismatch produces a Pinecone query error surfaced as a `500` with the message `"Pinecone query failed: …"`.
### Example knowledge node configuration
A workflow knowledge node configured for Pinecone looks like this:
```json Pinecone knowledge node config
{
"credential_id": "cred_abc",
"provider_type": "pinecone",
"collection_name": "product-docs",
"namespace": "v1",
"query": "{{trigger.question}}",
"top_k": 5,
"min_score": 0.3,
"filters": { "category": { "$eq": "docs" } },
"output_format": "context",
"embedding_config": {
"integration_name": "openai",
"provider_id": "openai",
"model_id": "text-embedding-3-small",
"credential_id": null
}
}
```
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4142 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** Knowledge node inspector configured for Pinecone.
**[SCREENSHOT_DETAILS]:** Capture the knowledge node inspector with provider type set to Pinecone, the index (collection) name, namespace, top_k, min_score, and the embedding model selector populated. Highlight that an embedding model is required. Light theme.
## How ModuleX queries Pinecone
When the knowledge node runs, ModuleX builds and sends the Pinecone query directly. Understanding the exact request helps when debugging connectivity or 404s.
### Request to Pinecone
ModuleX `POST`s to `{index_url}/query` with these headers:
```http Headers sent to Pinecone
Api-Key:
Content-Type: application/json
```
and this body:
```json Pinecone query body
{
"vector": [0.0123, -0.0456, "..."],
"topK": 5,
"includeMetadata": true,
"includeValues": false,
"namespace": "v1",
"filter": { "category": { "$eq": "docs" } }
}
```
`namespace` and `filter` are only included when set. The request times out after 30 seconds.
### Index URL resolution
ModuleX builds the index host in this order:
1. If your credential `auth_data` contains `index_host`, ModuleX uses that exact URL.
2. Otherwise, ModuleX derives the host from the environment as `https://{index_name}-{environment}.svc.pinecone.io`.
The connection test and `list_indexes` instead call the controller URL `https://controller.{environment}.pinecone.io/indexes`, while the saved-credential test uses `https://api.pinecone.io/indexes`.
The environment-derived host (`https://{index_name}-{environment}.svc.pinecone.io`) and the controller host (`https://controller.{environment}.pinecone.io`) follow Pinecone's **legacy pod-based** URL conventions. Pinecone **serverless** indexes use a different host. If your queries return connection errors or `404` despite a valid key, set `index_host` in `auth_data` to the exact host shown in your Pinecone console. {/* TODO: confirm the connect UI exposes index_host; today it is read by the adapter (pinecone_adapter.py:59-60) but not declared in the manifest fields. */}
### Normalized result
ModuleX maps each Pinecone match into a standard result object before formatting:
The Pinecone match id (the vector id).
Pinecone's raw similarity score for the match. Matches below `min_score` are dropped before this point.
Text extracted from the match metadata. ModuleX checks common metadata fields in order: `content`, `text`, `chunk_text`, `page_content`, `data`, `body`, `summary`, `document`. If none are present, `content` is empty — store your chunk text under one of these keys in Pinecone metadata so retrieved chunks carry usable text.
The match metadata, included when `include_metadata` is `true`.
The stored vector values, included only when vector values are requested.
These results are then shaped into `chunks`, `context`, or `both` per the node's `output_format`.
## Billing
BYOK retrieval through Pinecone is **not metered in ModuleX credits**. Only knowledge bases whose embedding provider is managed (`modulexdb` / `modulexai`) reserve retrieval credits. Two cost notes still apply:
- **Pinecone bills you directly** for queries and storage on your own account.
- **The query embedding may be metered.** If your `embedding_config` uses a managed embedding model, generating the query vector is billed in ModuleX credits like any other managed model call. Using a BYOK embedding credential avoids that. See [credits & metering](/billing/credits).
## Errors and edge cases
A bad or revoked key returns `401` from Pinecone. ModuleX surfaces this as an authentication error (`"Invalid Pinecone API key"`). Re-test the credential with `POST /credentials/{credential_id}/test` and rotate the key in Pinecone if needed.
If Pinecone returns `404` for the query, ModuleX raises `"Index not found: "`. Verify the `collection_name` matches an index in your project, and check the [Index URL resolution](#index-url-resolution) rules — a serverless index on the legacy host pattern is the usual cause. Set `index_host` to fix it.
Pinecone requires a pre-computed query vector. Without `embedding_config`, the node raises `"embedding_config required for providers that don't handle embeddings…"` and never calls Pinecone. Add an `embedding_config` whose dimension matches your index.
The node raises `"collection_name is required for external provider: pinecone"`. Set `collection_name` to your index name.
Any other Pinecone error (for example a vector-dimension mismatch) surfaces as a `500` with `"Pinecone query failed: "`. Confirm your embedding model dimension equals the index dimension.
Pinecone returns vector ids, scores, and metadata — not separate text. If retrieved chunks have empty `content`, store the chunk text in metadata under one of the recognized keys (`content`, `text`, `chunk_text`, `page_content`, `data`, `body`, `summary`, `document`).
## Provider actions reference
Beyond workflow retrieval, the Pinecone integration declares three catalog actions, surfaced through the knowledge-provider catalog and the [tool node](/workflow-builder/nodes/tool). Authentication is the same `custom` API-key schema described above.
Performs a vector similarity search on a Pinecone index.
**Parameters**
Name of the Pinecone index to search.
Namespace within the index.
Query embedding vector.
Number of results to return.
Metadata filter conditions.
Include metadata in results.
Include vector values in results.
**Output**
Array of matches, each with `id`, `score`, `metadata`, and `values`.
The namespace searched.
Lists all indexes in your Pinecone project. Takes no parameters.
**Output:** an array of indexes, each with `name`, `dimension`, `metric`, and `status`.
Returns statistics about one index.
**Parameters**
Name of the index.
**Output**
The index vector dimension.
Total vectors in the index.
Per-namespace vector counts.
## Related pages
Compare managed and BYOK vector stores and see all supported providers.
Configure retrieval inside a workflow.
Create, rotate, and scope credentials in the app and via API.
How ModuleX retrieves company knowledge end to end.
---
# Qdrant
URL: https://docs.modulex.dev/integrations/knowledge-providers/qdrant
Connect Qdrant as a bring-your-own vector store in ModuleX: create a Qdrant connection credential, configure a Knowledge node to query your collections, and understand BYOK retrieval with no ModuleX credit cost.
Qdrant is a **bring-your-own (BYOK) external knowledge provider** in ModuleX. You connect your own Qdrant instance — Qdrant Cloud or self-hosted — as a [credential](/concepts/credentials-oauth), then point a workflow [Knowledge node](/workflow-builder/nodes/knowledge) at one of your collections to run vector similarity search at run time. Because retrieval runs against your own Qdrant, it is **uncosted** in ModuleX: it consumes **no [credits](/concepts/credits-billing)** and never hits the billing gate.
This page covers connecting a Qdrant credential, the connection fields and Knowledge-node configuration, how BYOK retrieval works under the hood, the catalog actions Qdrant exposes, and the errors you can hit. For the cross-provider picture see [Knowledge providers](/integrations/knowledge-providers/overview); for the managed (credit-metered) alternative see [modulexdb](/integrations/knowledge-providers/modulexdb); for the retrieval concept see [Knowledge & RAG](/concepts/knowledge-rag).
Qdrant is the integration named `qdrant` on the wire, with `integration_type` `knowledge_provider`. It ships **one auth schema** of type `custom` ("Qdrant Connection"). Unlike [managed knowledge](/platform/knowledge/managed) (the `modulexdb` provider), ModuleX does **not** ingest, chunk, embed, or store documents for you in Qdrant — you own the collections, the points, and the embeddings. ModuleX only **queries** what is already in your Qdrant.
## How Qdrant fits in ModuleX
ModuleX treats a vector store one of two ways:
ModuleX hosts the vectors, ingests and embeds your documents, and bills retrieval and ingest in [credits](/concepts/credits-billing). See [Managed knowledge](/platform/knowledge/managed).
You host the vectors in your own Qdrant. ModuleX queries them through an adapter using a [credential](/concepts/credentials-oauth) you create. Retrieval is **uncosted** — no credits, no billing gate.
Qdrant requires a **query vector** — it does not embed text for you. So a Knowledge node pointed at Qdrant first embeds your query with the embedding model you configure (for example an [OpenAI](/integrations/llm-providers/openai) embedding model), then sends that vector to Qdrant's search API. This means a Qdrant Knowledge node needs an `embedding_config`; ModuleX raises a configuration error without one.
The embedding model used at query time **must match** the model that produced the vectors already stored in your Qdrant collection — same provider, same model, same dimension. If they differ, Qdrant returns either a dimension-mismatch error or low-quality results. ModuleX does not validate this for you because it never wrote those vectors.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4130 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** Diagram of the BYOK Qdrant retrieval path inside a workflow run.
**[IMAGE_DETAILS]:** Show: workflow Knowledge node receives a query string, then "embed query" using the configured embedding model (e.g. OpenAI), producing a vector; the vector plus collection name go to the user's Qdrant instance over its REST API (`POST /collections/{name}/points/search`); matched points return to the node, which formats them as chunks or a context string into run state. Annotate "BYOK — runs on your Qdrant, no ModuleX credits". Light theme, 16:9, left-to-right flow.
## Before you start
A Qdrant Cloud cluster or a self-hosted Qdrant that ModuleX can reach over HTTP(S), with at least one collection that already contains embedded points.
Creating and managing credentials, and browsing the integration catalog, require the **owner** or **admin** role in your [organization](/concepts/organizations-roles). The retired `member` role cannot do this. See [Roles & permissions](/security/roles-permissions).
Every API call sends `Authorization: Bearer mx_live_…` and `X-Organization-ID`. See [Authentication](/api-reference/authentication).
Know which embedding model and dimension produced the vectors in your collection, so you can configure the same model for query embedding.
## Connect Qdrant
You connect Qdrant by creating a `custom` [credential](/concepts/credentials-oauth) for the `qdrant` integration. The credential stores your Qdrant URL and (optionally) an API key. ModuleX encrypts the credential at rest and never returns the secret material in clear text.
Note your Qdrant **URL** (including the port — Qdrant's REST API listens on `6333` by default) and, for Qdrant Cloud, your **API key**. A local instance typically needs no API key.
Call `POST /credentials/test-temporary` to check the connection **before** persisting it. ModuleX runs Qdrant's configured test — a `GET {url}/collections` with your `api-key` header — and reports `is_valid`. See [Validate a connection before saving](#validate-a-connection-before-saving).
Call `POST /credentials` with `integration_name: "qdrant"`, `auth_type: "custom"`, and an `auth_data` object holding `url` and optional `api_key`. Set `make_default: true` to make it the default Qdrant credential for the organization.
Use the returned `credential_id` (plus a `collection_name` and an `embedding_config`) in a workflow [Knowledge node](/workflow-builder/nodes/knowledge). See [Configure a Knowledge node for Qdrant](#configure-a-knowledge-node-for-qdrant).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4131 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The ModuleX app credential dialog for connecting Qdrant.
**[SCREENSHOT_DETAILS]:** Capture the "Connect Qdrant" / "Qdrant Connection" credential form in the integrations/credentials area of the app. Show the Qdrant logo, the **Qdrant URL** field (placeholder `https://xyz-abc.aws.cloud.qdrant.io:6333`), the optional **API Key** field (masked, marked optional, placeholder `qdrant-api-key-...`), the "Set as default" toggle, and the Test/Save buttons. Light theme, 16:9, crop to the dialog.
### Connection fields
The Qdrant auth schema is a single `custom` schema named **"Qdrant Connection"** with two fields. Send them inside `auth_data`.
The base URL of your Qdrant instance, including the port — for example `https://xyz-abc.aws.cloud.qdrant.io:6333`. A trailing slash is stripped. When omitted at run time the adapter falls back to `http://localhost:6333`, but the field is **required** when you create a credential. Not sensitive.
Your Qdrant Cloud API key. Optional — leave it unset for local or unauthenticated instances. Sent to Qdrant as the `api-key` request header. Sensitive; stored encrypted and masked in responses.
### Create the credential
`POST /credentials` returns `201`. For Qdrant you must send `auth_type: "custom"` because the connection is not an `api_key`-only schema (the URL is part of the connection). See the full credential model in [Credentials & OAuth2](/concepts/credentials-oauth).
Must be `qdrant`.
`custom`.
The connection material — `{"url": "...", "api_key": "..."}`. `api_key` may be omitted for instances that do not require one.
A human-readable label. Defaults to the integration's display name (`Qdrant`) when omitted.
Set this credential as the default Qdrant credential for the organization. Only one credential per integration can be the default.
**Response** — `201 Created` (secret masked):
The credential's UUID. Pass this as `credential_id` in a Knowledge node to use this Qdrant connection.
`qdrant`.
`knowledge_provider`.
`custom`.
Whether this is the organization's default Qdrant credential.
ISO-8601 timestamp of the last resolution, or `null` if never used.
```bash cURL
curl -X POST https://api.modulex.dev/credentials \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "qdrant",
"auth_type": "custom",
"display_name": "Production Qdrant",
"make_default": true,
"auth_data": {
"url": "https://xyz-abc.aws.cloud.qdrant.io:6333",
"api_key": "qdrant-api-key-abc123"
}
}'
```
```python Python
from modulex import Modulex
async with Modulex(
api_key="mx_live_xxx",
organization_id="11111111-1111-1111-1111-111111111111",
) as client:
credential = await client.credentials.create(
"qdrant",
auth_type="custom",
display_name="Production Qdrant",
make_default=True,
auth_data={
"url": "https://xyz-abc.aws.cloud.qdrant.io:6333",
"api_key": "qdrant-api-key-abc123",
},
)
print(credential.credential_id)
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_xxx",
organizationId: "11111111-1111-1111-1111-111111111111",
});
const credential = await client.credentials.create({
integrationName: "qdrant",
authType: "custom",
displayName: "Production Qdrant",
makeDefault: true,
authData: {
url: "https://xyz-abc.aws.cloud.qdrant.io:6333",
api_key: "qdrant-api-key-abc123",
},
});
console.log(credential.credential_id);
```
### Validate a connection before saving
`POST /credentials/test-temporary` validates the connection **before** you persist it. ModuleX runs Qdrant's configured test endpoint — `GET {url}/collections`, sending the `api-key` header — and treats HTTP `200` with a `result` field present as success. The test is free (`cost_level: "free"`).
`qdrant`.
`custom`.
`{"url": "...", "api_key": "..."}`.
The response reports `is_valid`, a human-readable `message`, `tested_at`, the `test_method`, and the `status_code` returned by Qdrant.
```bash cURL
curl -X POST https://api.modulex.dev/credentials/test-temporary \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "qdrant",
"auth_type": "custom",
"auth_data": {
"url": "https://xyz-abc.aws.cloud.qdrant.io:6333",
"api_key": "qdrant-api-key-abc123"
}
}'
```
```python Python
result = await client.credentials.test_temporary(
"qdrant",
"custom",
{
"url": "https://xyz-abc.aws.cloud.qdrant.io:6333",
"api_key": "qdrant-api-key-abc123",
},
)
print(result.is_valid, result.message)
```
```javascript JavaScript
const result = await client.credentials.testTemporary({
integrationName: "qdrant",
authType: "custom",
authData: {
url: "https://xyz-abc.aws.cloud.qdrant.io:6333",
api_key: "qdrant-api-key-abc123",
},
});
console.log(result.isValid, result.message);
```
## Configure a Knowledge node for Qdrant
A workflow [Knowledge node](/workflow-builder/nodes/knowledge) is the surface that retrieves from Qdrant during a [run](/concepts/workflows-and-runs). For an external provider you set `provider_type` to `qdrant`, point it at a `collection_name`, and supply an `embedding_config` so ModuleX can embed the query before searching. The full node configuration is below; fields marked **(external)** apply to Qdrant and the other [external providers](/integrations/knowledge-providers/overview), and fields marked **(native only)** apply only to [modulexdb](/integrations/knowledge-providers/modulexdb).
The UUID of the Qdrant [credential](/concepts/credentials-oauth) to use.
One of `modulexdb`, `qdrant`, `pinecone`, `weaviate`, `mongodb_atlas`. Set it to `qdrant`.
The search query. Supports `{{nodeId.path}}` references so the query can come from an earlier node's output. See [Variables & references](/workflow-builder/variables-and-references).
When `true`, use the workflow input as the query instead of the `query` field.
**(external)** The Qdrant collection to search. Required for Qdrant — the node raises a configuration error without it.
**(external)** Namespace, used by [Pinecone](/integrations/knowledge-providers/pinecone)-style providers. Qdrant does not use namespaces; leave it unset.
**(external)** Required for Qdrant. The model ModuleX uses to embed the query into a vector before searching Qdrant. See [The `embedding_config` object](#the-embedding-config-object).
Number of results to retrieve. Range `1`–`50`. Passed to Qdrant as the search `limit`.
Minimum similarity-score floor, `0.0`–`1.0`. When greater than `0`, sent to Qdrant as `score_threshold`; Qdrant drops points below it.
Maximum tokens in the formatted context string (used when `output_format` is `context` or `both`). Range `100`–`10000`.
**(external)** A provider-specific filter, passed straight to Qdrant as its `filter` clause. Use Qdrant's filter syntax (for example `must`/`should`/`must_not` conditions on payload fields).
**(native only)** Restrict retrieval to specific document IDs. Applies to modulexdb knowledge bases, not Qdrant.
How results are written into run state — `chunks` (individual matches with metadata), `context` (one RAG-ready context string), or `both`.
Include each match's payload/metadata in the results. Maps to Qdrant's `with_payload`.
Include source-document info in the formatted context string.
### The `embedding_config` object
Qdrant stores vectors but does not embed text, so the Knowledge node embeds your query first. `embedding_config` selects the embedding model and is **required** for Qdrant.
The embedding provider integration, for example `openai`. See [LLM providers](/integrations/llm-providers/overview).
The provider routing slug, for example `openai`.
The embedding model id, for example `text-embedding-3-small`. Must match the model that produced the vectors in your collection.
The credential for the embedding provider. When `null`, ModuleX uses the organization's default credential for `integration_name`.
```json Knowledge node config (Qdrant)
{
"credential_id": "c0ffee00-1111-2222-3333-444455556666",
"provider_type": "qdrant",
"collection_name": "product_docs",
"query": "{{trigger.question}}",
"top_k": 5,
"min_score": 0.3,
"output_format": "context",
"embedding_config": {
"integration_name": "openai",
"provider_id": "openai",
"model_id": "text-embedding-3-small",
"credential_id": null
}
}
```
The Knowledge node is configured on the canvas in the [workflow builder](/workflow-builder/nodes/knowledge), or programmatically as part of a workflow's node graph. There is no standalone REST endpoint that queries an external provider directly — Qdrant retrieval happens **inside a workflow run**. The native [knowledge-bases search API](/platform/knowledge/managed) (`POST /knowledge-bases/{id}/search`) targets modulexdb, not Qdrant.
## How BYOK retrieval works
When a Knowledge node with `provider_type: "qdrant"` executes during a run, ModuleX:
Loads your Qdrant credential for the current organization and decrypts the `url` and `api_key`. A missing or wrong-org credential fails the node with a credential error. See [Data security & encryption](/security/data-encryption).
Because Qdrant requires a query vector, ModuleX embeds the resolved `query` using your `embedding_config`. Without `embedding_config`, the node raises a configuration error.
The Qdrant adapter calls `POST {url}/collections/{collection_name}/points/search` with the query vector, `limit` (`top_k`), `with_payload` (`include_metadata`), `with_vector`, an optional `score_threshold` (`min_score`), and any `filters`. It sends the `api-key` header when an API key is set.
Each Qdrant point becomes a standard match (`id`, `score`, extracted text content, payload metadata). Text content is pulled from common payload fields (`content`, `text`, `chunk_text`, `page_content`, `data`, `body`, `summary`, `document`). The node then writes them into run state as chunks, a context string, or both per `output_format`. See [Workflow engine & nodes](/concepts/workflow-engine).
Text-content extraction depends on your payload using one of the recognized field names. If your Qdrant points store their text under a different key, the returned `content` is empty (the metadata still comes through when `include_metadata` is on). Store retrievable text under a field such as `content` or `text`.
## BYOK billing
Qdrant is **bring-your-own**. Retrieval runs against your Qdrant instance and is **not** metered in ModuleX [credits](/concepts/credits-billing). Only **managed** knowledge — `modulexdb` knowledge bases — is credit-billed for retrieval and ingest.
Querying Qdrant draws down no plan allowance and no [wallet](/billing/wallet) balance. There is no per-retrieval credit cost.
Because BYOK retrieval is uncosted, a Qdrant Knowledge node never produces the `402`/`403`/`429` `DenialEnvelope` that managed knowledge can. See [Usage gating & limits](/billing/usage-gating).
The query-embedding step uses your `embedding_config`. If that points at a [BYOK model](/integrations/llm-providers/overview) (for example OpenAI), the embedding is billed by that provider. If it points at a managed model, the embedding is credit-metered.
Storage, indexing, and query throughput for your Qdrant are governed by your Qdrant Cloud plan or self-hosted capacity, not by ModuleX.
## Browse Qdrant in the catalog
The [integration catalog](/integrations/catalog) is the read-only discovery surface. Use it to fetch Qdrant's metadata, actions, and auth schema. These catalog endpoints authenticate with a **Clerk JWT** (the app token) rather than an `mx_live_*` API key, and still require `X-Organization-ID` and the owner/admin role.
`qdrant`.
**Response** — `200 OK`, an `IntegrationDetail`:
`qdrant`.
`Qdrant`.
`knowledge_provider`.
`["Vector Database", "semantic-search"]`.
The catalog actions Qdrant declares — `query`, `list_collections`, `get_collection_info`. See [Catalog actions](#catalog-actions).
The single `custom` "Qdrant Connection" schema, with its `fields` (`url`, `api_key`) and a `test_endpoint`.
`null` for Qdrant (the package/JSON manifest carries `app_url` `https://qdrant.tech` but no `docs_url`).
The integration's `extra_metadata`. Note `provider_type` (`external`) is present in the source manifest but is **dropped on sync** and is not returned by the catalog API.
Knowledge-provider auth schemas use a `fields` array (not the `setup_environment_variables` array used by LLM/tool manifests). The catalog returns `auth_schemas` verbatim, so when you read a knowledge-provider detail, look for `fields`.
```bash cURL
curl https://api.modulex.dev/integrations/knowledge-providers/qdrant \
-H "Authorization: Bearer " \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111"
```
```bash cURL — list all knowledge providers
curl https://api.modulex.dev/integrations/knowledge-providers \
-H "Authorization: Bearer " \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111"
```
```json
{
"name": "qdrant",
"display_name": "Qdrant",
"description": "High-performance vector database with advanced filtering capabilities for semantic search",
"logo": "logos:qdrant-icon",
"app_url": "https://qdrant.tech",
"docs_url": null,
"categories": ["Vector Database", "semantic-search"],
"integration_type": "knowledge_provider",
"version": "1.0.0",
"auth_schemas": [
{
"auth_type": "custom",
"display_name": "Qdrant Connection",
"description": "Connect to your Qdrant instance using URL and optional API key",
"fields": [
{
"name": "url",
"display_name": "Qdrant URL",
"type": "string",
"required": true,
"sensitive": false,
"sample_format": "https://xyz-abc.aws.cloud.qdrant.io:6333"
},
{
"name": "api_key",
"display_name": "API Key",
"type": "string",
"required": false,
"sensitive": true,
"sample_format": "qdrant-api-key-..."
}
],
"test_endpoint": {
"url": "{url}/collections",
"method": "GET",
"headers": { "api-key": "{api_key}", "Content-Type": "application/json" },
"success_indicators": { "status_codes": [200], "response_fields": ["result"] },
"cost_level": "free"
}
}
],
"actions": [
{ "name": "query", "description": "Perform vector similarity search on your Qdrant collection" },
{ "name": "list_collections", "description": "List all collections in the Qdrant instance" },
{ "name": "get_collection_info", "description": "Get information about a specific collection" }
]
}
```
### Catalog actions
Qdrant declares three actions in its manifest. These describe the operations the provider exposes; in practice they are driven by the [Knowledge node](#configure-a-knowledge-node-for-qdrant) (`query`) and used for connection discovery (`list_collections`, `get_collection_info`).
Performs vector similarity search on a Qdrant collection. Maps to `POST {url}/collections/{collection_name}/points/search`.
Name of the Qdrant collection to search.
The query embedding vector. Qdrant does not embed text — supply a vector. In a Knowledge node, ModuleX computes this from your `embedding_config`.
Maximum number of results to return.
Minimum similarity score (`0`–`1`). Applied only when greater than `0`.
Optional Qdrant filter conditions for the search.
Include each point's payload in the results.
Include the stored vectors in the results.
**Result** — an array of points, each:
The point id.
The similarity score.
The point payload (when `with_payload` is true).
The stored vector (when `with_vectors` is true).
Lists all collections in the Qdrant instance. Takes no parameters. Maps to `GET {url}/collections` (with a per-collection info lookup for counts).
**Result** — an array, each:
The collection name.
Number of vectors (points) in the collection.
Number of points in the collection.
Returns details about one collection. Maps to `GET {url}/collections/{collection_name}`.
Name of the collection.
**Result**:
The collection name.
Number of vectors in the collection.
Number of points in the collection.
The collection configuration, including its vector parameters (size/dimension and distance metric).
## Errors and edge cases
A Qdrant Knowledge node without `collection_name` fails with a configuration error before any call to Qdrant.
Qdrant requires a query vector. Without `embedding_config`, the node fails with an error asking you to configure `integration_name`, `provider_id`, `model_id`, and optionally `credential_id`.
If the `credential_id` does not resolve in the current organization, the node fails with a credential-not-found error. Confirm the credential belongs to the org set in `X-Organization-ID`.
Qdrant returning `401` surfaces as an authentication error ("Invalid API key"). Re-check the `api_key` in your credential.
Qdrant returning `404` for the search surfaces as a query error (`Collection not found: {name}`). Verify the collection exists on that instance.
If ModuleX cannot reach the Qdrant URL, the node fails with a connection error. Confirm the URL, port (`6333` by default), and that the instance is reachable from ModuleX.
If the query vector's dimension does not match the collection's vector size, Qdrant rejects the search. Use an embedding model whose dimension matches the collection.
These errors arise inside a [workflow run](/concepts/workflows-and-runs), so they appear as node/run errors in the run stream rather than as a top-level HTTP error envelope. For the error-envelope shapes on the REST surface, see [Errors & status codes](/api-reference/errors).
## Managing the credential
Day-to-day operations use the standard [credentials API](/concepts/credentials-oauth#the-credentials-api). For Qdrant specifically:
- **Rotate the URL or key.** Secrets are immutable through `PUT /credentials/{id}` (that route updates only `display_name` and metadata). To change the URL or API key, create a new Qdrant credential and delete the old one.
- **Set the default.** `POST /credentials/{id}/set-default` makes one Qdrant credential the organization default, used when a node resolves to the default.
- **Test a saved connection.** `POST /credentials/{id}/test` re-runs Qdrant's test endpoint against the stored URL and key.
- **Delete.** `DELETE /credentials/{id}` removes it and returns `204`. Knowledge nodes pointing at it will fail credential resolution until another valid Qdrant credential exists.
See [Managing credentials](/integrations/managing-credentials) for the app workflow and [Credentials & OAuth2](/concepts/credentials-oauth) for the complete API.
## Where to go next
Compare Qdrant with modulexdb and the other external vector stores.
The credit-metered, ModuleX-hosted alternative that ingests and embeds for you.
Configure retrieval inside a workflow, including external providers like Qdrant.
How ModuleX retrieves company knowledge — managed and BYOK.
---
# Weaviate as a vector store
URL: https://docs.modulex.dev/integrations/knowledge-providers/weaviate
Connect a Weaviate cluster to ModuleX as a bring-your-own-key knowledge provider, configure the knowledge node, and run vector retrieval against your own classes.
Weaviate is an open-source vector database with a GraphQL query API. In ModuleX, Weaviate is a **bring-your-own-key (BYOK) knowledge provider**: you store the connection details for your own cluster as a credential, and a [knowledge node](/workflow-builder/nodes/knowledge) in a workflow runs vector similarity search against one of your Weaviate classes. ModuleX never hosts your vectors and does not charge credits for retrieval against a Weaviate cluster you own — see [Billing](#billing-byok-retrieval-is-not-metered).
If you want ModuleX to host the vectors, ingest, embed, and search for you, use [modulexdb (managed)](/integrations/knowledge-providers/modulexdb) instead. For the full list of supported stores, see [Knowledge providers](/integrations/knowledge-providers/overview).
Weaviate retrieval in ModuleX runs **inside a workflow knowledge node**, not through the managed `/knowledge-bases` search API. The managed search, ingest, and document endpoints under `/knowledge-bases` operate only on `modulexdb`-backed knowledge bases. With Weaviate you bring vectors that already exist in your own cluster.
## How Weaviate fits into ModuleX
ModuleX treats Weaviate as an external provider behind a single adapter. At run time, a knowledge node:
The node looks up your stored Weaviate credential by `credential_id`, scoped to the organization in `X-Organization-ID`, and decrypts the connection details (`url` and optional `api_key`).
Weaviate retrieval in ModuleX requires a query vector. ModuleX generates the embedding from the node's `embedding_config` (for example an OpenAI `text-embedding-3-small` model) before calling Weaviate. See [embedding configuration](#embedding-configuration).
The adapter issues a `Get` GraphQL query with a `nearVector` argument against your class, applies a `certainty` floor derived from `min_score`, and limits results to `top_k`.
Matches are normalized into ModuleX's standard chunk shape and returned as `chunks`, a single `context` string, or `both`, depending on `output_format`.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4160 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** Data-flow diagram of BYOK Weaviate retrieval inside a knowledge node.
**[IMAGE_DETAILS]:** Show: workflow knowledge node -> resolve Weaviate credential (url + optional api_key) -> embed query via embedding_config -> nearVector GraphQL POST to the customer's Weaviate cluster -> normalized chunks back into run state. Mark the cluster boundary as customer-owned (BYOK, uncosted). Match the docs accent palette; light and dark variants; 16:9.
## Connect Weaviate
A Weaviate connection is stored as a credential with the `custom` auth type and the integration name `weaviate`. Creating a credential requires the **owner** or **admin** role on the organization (`organization_admin_required`); the `member` role is retired and cannot create credentials. See [Roles & permissions](/security/roles-permissions).
Authenticate every request to the ModuleX API with `Authorization: Bearer mx_live_…` and the `X-Organization-ID` header, as described in [Authentication](/api-reference/authentication).
### Connection fields
These are the two fields the Weaviate auth schema exposes. They are stored, encrypted at rest, inside the credential's `auth_data`.
The base URL of your Weaviate instance, with no trailing path. Example: `https://your-cluster.weaviate.cloud`. If omitted at query time the adapter falls back to `http://localhost:8080`, but you should always set it explicitly. Stored unencrypted-flagged (`sensitive: false`).
The Weaviate API key. **Required for Weaviate Cloud**; optional for an unauthenticated self-hosted cluster. When present, ModuleX sends it to Weaviate as `Authorization: Bearer `. Stored as a secret (`sensitive: true`).
### Create the credential
Send the connection fields under `auth_data` with `auth_type` set to `custom`. The response returns the new `credential_id`, which you then reference from the knowledge node.
```bash cURL
curl -X POST https://api.modulex.dev/credentials \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: org_123" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "weaviate",
"auth_type": "custom",
"display_name": "Production Weaviate",
"auth_data": {
"url": "https://your-cluster.weaviate.cloud",
"api_key": "weaviate-api-key-..."
}
}'
```
```python Python
from modulex import AsyncModulex
client = AsyncModulex(
api_key="mx_live_xxx",
organization_id="org_123",
)
credential = await client.credentials.create(
integration_name="weaviate",
auth_type="custom",
display_name="Production Weaviate",
auth_data={
"url": "https://your-cluster.weaviate.cloud",
"api_key": "weaviate-api-key-...",
},
)
print(credential["credential_id"])
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_xxx",
organizationId: "org_123",
});
const credential = await client.credentials.create({
integration_name: "weaviate",
auth_type: "custom",
display_name: "Production Weaviate",
auth_data: {
url: "https://your-cluster.weaviate.cloud",
api_key: "weaviate-api-key-...",
},
});
console.log(credential.credential_id);
```
Send `auth_type: "custom"` explicitly. Without it, the backend infers the credential type from `auth_data`: a payload containing `api_key` is treated as a standard API-key credential, which is the wrong shape for Weaviate (it would drop the `url`). The explicit `custom` type keeps both fields together in one credential.
For the broader credential lifecycle — listing, testing, setting a default, and rotation — see [Managing credentials](/integrations/managing-credentials).
### Test the connection
Testing a Weaviate credential validates connectivity rather than running a search. ModuleX calls your cluster's readiness probe at `GET {url}/v1/.well-known/ready` and, on success, reads `GET {url}/v1/schema` to count your classes.
| Outcome | Meaning |
| --- | --- |
| `status: "connected"` plus `classes_count` | The cluster is reachable and the API key (if any) is valid. |
| `401` from Weaviate | The `api_key` is missing or invalid for a cluster that requires authentication. |
| Connection refused / not ready | The `url` is wrong, the cluster is down, or it is not reachable from ModuleX. |
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4161 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The Weaviate connection form in the ModuleX credentials UI.
**[SCREENSHOT_DETAILS]:** Capture the "Add credential" panel for Weaviate showing the URL field (required) and API Key field (optional, masked), with the Test connection result showing "connected" and a class count. Settings > Credentials in the live app; dark theme; crop to the form.
## Configure the knowledge node
Once the credential exists, add a [knowledge node](/workflow-builder/nodes/knowledge) to a workflow and point it at Weaviate. The node config (`KnowledgeNodeConfig`) is shared across all providers; the fields below are the ones that matter for Weaviate. Every node value supports `{{nodeId.path}}` references so a query can come from a previous step — see [Variables & references](/workflow-builder/variables-and-references).
### Connection and provider
Set to `weaviate` to route the node through the Weaviate adapter. The other accepted values are `modulexdb`, `qdrant`, `pinecone`, and `mongodb_atlas`.
The `credential_id` of the Weaviate credential you created above.
The Weaviate **class** to search (Weaviate's term for a collection). Required for every external provider; the node raises a validation error if it is missing for a non-`modulexdb` provider.
Accepted on the node config for Pinecone-style providers. **The Weaviate adapter ignores it** — Weaviate has no namespace concept, so leave it unset.
### Query
The search text. Supports `{{nodeId.path}}` references for dynamic queries. ModuleX embeds this text into a vector before calling Weaviate (see [embedding configuration](#embedding-configuration)).
When `true`, the node uses the workflow input as the query instead of the `query` field, reading the first of `query`, `question`, `input`, `user_input`, or `message` found in run state.
### Retrieval settings
Number of results to return. Range `1`–`50`. Maps to the GraphQL `limit` argument.
Minimum similarity threshold, `0.0`–`1.0`. For Weaviate the adapter converts this to a `certainty` floor as `certainty = 1.0 - min_score` (only when `min_score > 0`; otherwise `certainty` is `0.0` and no floor is applied). The returned `score` for each match is Weaviate's `certainty` value.
Token budget for the assembled `context` string. Range `100`–`10000`. Applies when `output_format` is `context` or `both`.
Provider-specific filter conditions passed through to the adapter. For Weaviate these correspond to GraphQL `where` conditions.
Restrict results to specific document IDs. **Native (`modulexdb`) knowledge bases only** — this filter is not applied to Weaviate.
### Output
How retrieved knowledge is returned: `chunks` (individual matches with metadata), `context` (a single formatted RAG string), or `both`.
Include each match's properties (returned by Weaviate as object properties) in the chunk metadata.
Include source document headers in the formatted `context` string.
### Embedding configuration
Weaviate retrieval in ModuleX **always requires a query vector** — the adapter reports `requires_query_embedding() = true` and raises `Weaviate requires query_vector for search` if none is supplied. ModuleX builds that vector from the node's `embedding_config` before calling your cluster, so this object is required for Weaviate.
Use the **same embedding model** that produced the vectors stored in your Weaviate class. Mismatched models yield dimension errors or meaningless similarity scores. ModuleX does not read your class's vectorizer config to infer the model; you declare it in `embedding_config`.
Embedding settings for generating the query vector.
Integration name of the embedding provider, for example `openai` or `cohere`.
Provider identifier, for example `openai`.
Embedding model id, for example `text-embedding-3-small`. Must match the model used to index your Weaviate class.
Credential for the embedding provider. If omitted, ModuleX uses the organization's default credential for `integration_name`.
ModuleX's `text2vec`-style server-side text search is **not** wired through this adapter. Although the catalog metadata for Weaviate lists a `query_text` parameter and mentions `nearText`, the live retrieval path uses `nearVector` only and rejects a search with no `query_vector`. Plan to provide vectors via `embedding_config`.
## BYOK retrieval
A complete Weaviate knowledge node configuration, ready to drop into a workflow's node definition `config`:
```json Knowledge node config (Weaviate)
{
"provider_type": "weaviate",
"credential_id": "a1b2c3d4-0000-0000-0000-000000000000",
"collection_name": "ProductDocs",
"query": "{{trigger.question}}",
"top_k": 5,
"min_score": 0.3,
"output_format": "context",
"include_metadata": true,
"include_source": true,
"embedding_config": {
"integration_name": "openai",
"provider_id": "openai",
"model_id": "text-embedding-3-small",
"credential_id": null
}
}
```
When this node runs, ModuleX embeds `{{trigger.question}}`, issues the `nearVector` GraphQL query against the `ProductDocs` class, and writes the result to run state under the node's own `id`. A downstream [LLM node](/workflow-builder/nodes/llm) or [Agent node](/workflow-builder/nodes/agent) can then reference the retrieved context with `{{.context}}`.
To run the workflow itself over the API or an SDK, see [Run via API](/workflow-builder/execution/api-endpoint) and the [Run a workflow](/guides/run-a-workflow) guide. The run streams over SSE — see [SSE run streaming](/realtime/sse-streaming).
### What the adapter returns
Each match is normalized into a chunk. The `score` is Weaviate's `certainty`; `metadata` carries the object's returned properties; `content` is the adapter's best-effort text extraction from those properties.
The Weaviate object id (`_additional.id`).
The match's `certainty` from Weaviate (`0`–`1`, higher is better).
Text extracted from the object's properties. The adapter checks common field names in order: `content`, `text`, `chunk_text`, `page_content`, `data`, `body`, `summary`, `document`. If none is present, `content` may be empty — name a text property accordingly in your class.
The object's returned properties (everything except `_additional`). Present only when `include_metadata` is `true`.
### Returning specific properties
The Weaviate adapter requests result properties for you. If your class stores its text under a non-default property name, set `properties` in the node `filters`/config path appropriate to your build, or ensure one of the recognized field names above exists so `content` is populated. The catalog `query` action documents these tunables:
The Weaviate class to search.
The query embedding (`nearVector`). Supplied by ModuleX from `embedding_config`.
Maximum number of results.
Minimum certainty threshold (`0`–`1`). At run time this is derived from the node's `min_score`.
Properties to return in results. Defaults to an empty list, in which case the adapter returns the object id, certainty, and distance.
GraphQL `where` filter conditions.
## Billing: BYOK retrieval is not metered
Searching a Weaviate cluster you own does **not** consume ModuleX credits. ModuleX meters retrieval only for managed (`modulexdb`) knowledge — a managed search reserves one retrieval credit before the embed and records it on success. BYOK providers, including Weaviate, are uncosted for retrieval. See [Credits & metering](/billing/credits) and [Knowledge & RAG](/concepts/knowledge-rag).
The Weaviate **search** is uncosted, but the **workflow run** that contains the knowledge node is still subject to the run-admission billing gate. A run on the run / composer / assistant / knowledge-managed surfaces can be denied with a flat `DenialEnvelope` (`{code, layer, key, current, limit, reason}`) returned as `402`, `403`, or `429` when your plan allowance or wallet is exhausted. See [Usage gating & limits](/billing/usage-gating) and [Errors & status codes](/api-reference/errors). Embedding the query (via a managed embedding model) can itself consume credits even when the vector store is BYOK.
## Errors and edge cases
The adapter and node surface the following conditions. Adapter exceptions become the node's `error` field (the node returns empty `chunks`/`context` with an `error` rather than failing the whole run), while credential and config problems raise before the search.
- **`401` from Weaviate** — surfaces as an authentication error (`Invalid Weaviate API key`). Check the `api_key`; Weaviate Cloud requires one.
- **Connection refused / request error** — the `url` is unreachable from ModuleX or the cluster is down. Re-test the credential.
- **`Credential not found: `** — the `credential_id` is wrong or belongs to another organization. Credentials are strictly scoped to `X-Organization-ID`.
- **`collection_name is required for external provider`** — set `collection_name` to your Weaviate class.
- **`embedding_config required …`** — Weaviate needs a query vector; provide a valid `embedding_config`.
- **`Weaviate requires query_vector for search`** — raised if embedding produced no vector. Confirm the embedding model and its credential resolve.
- **GraphQL error** — surfaces as `Weaviate query failed: `. The most common cause is a class or property name that does not exist; verify the class with the cluster's schema and confirm property names.
- **Empty `content`** — the matched objects have no property among the recognized text field names; rename a property or store text under one of `content`/`text`/`chunk_text`/`page_content`.
- **No matches** — `min_score` may be too high (it tightens the `certainty` floor). Lower `min_score` toward `0` to widen results.
## Related pages
Compare every vector store ModuleX can use for retrieval.
The node that runs Weaviate retrieval inside a workflow.
How BYOK vector stores plug into ModuleX.
The retrieval model behind chats and workflows.
---
# Anthropic Claude models
URL: https://docs.modulex.dev/integrations/llm-providers/anthropic
Connect Anthropic to ModuleX with your own API key, see the available Claude models, and understand how BYOK usage is billed.
Anthropic is a [BYOK (bring-your-own-key)](/reference/glossary) LLM provider in ModuleX. You connect your own Anthropic API key, then use Claude models in the [LLM node](/workflow-builder/nodes/llm), the [Agent node](/workflow-builder/nodes/agent), [chat](/platform/chat/model-selection), and the [Assistant](/assistant/models-and-settings). Because Anthropic is BYOK, Anthropic bills you directly for token usage and ModuleX adds no credit charge on top — see [BYOK billing](#byok-billing) below.
For the full list of provider types and how managed versus BYOK selection works, see [LLM providers](/integrations/llm-providers/overview). If you would rather have ModuleX provision and meter the model for you in credits, use [ModuleX-managed models](/integrations/llm-providers/modulexai) instead.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4070 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The Anthropic connection card in the ModuleX integrations/credentials UI.
**[SCREENSHOT_DETAILS]:** Capture the API Key Authentication form for Anthropic in the credential-management UI: the `API Key` field (masked), the optional `Base URL` field defaulted to `https://api.anthropic.com`, and the "Test connection" / "Save" controls. Light theme, 16:9, crop to the card.
## What you need
Create a key in the [Anthropic Console](https://console.anthropic.com/settings/keys). Anthropic keys start with `sk-ant-` (for example `sk-ant-api03-…`). ModuleX validates the key against the pattern `^sk-ant-[a-zA-Z0-9\-_]{20,}$` before saving it.
Credentials are scoped to an [organization](/concepts/organizations-roles). Connecting and managing integrations requires the **owner** or **admin** role — the `member` role is retired. See [roles & permissions](/security/roles-permissions).
To connect Anthropic over the API or an SDK, you need a ModuleX API key (`mx_live_…`) and your organization id. See [authentication](/api-reference/authentication).
## Connect Anthropic
You connect Anthropic by storing your Anthropic API key as a [credential](/integrations/managing-credentials) for the `anthropic` integration. You can do this in the app or programmatically.
### In the app
1. Open the [integrations catalog](/integrations/catalog) and select **Anthropic**, or open **Settings → Credentials**.
2. Choose **API Key Authentication** and paste your Anthropic key.
3. Optionally set a custom **Base URL** (defaults to `https://api.anthropic.com`) — only needed for Anthropic-compatible gateways.
4. Save. ModuleX validates the key with a minimal request before storing it (see [Test a key before saving](#test-a-key-before-saving)).
Anthropic exposes a single authentication scheme — `api_key`. Its fields are:
Your Anthropic API key. Stored encrypted and never returned in plaintext. Pattern `^sk-ant-[a-zA-Z0-9\-_]{20,}$`; sample format `sk-ant-api03-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`.
Optional custom API base URL, only needed when pointing at an Anthropic-compatible API. Must match `^https?://.*`.
### Over the API or an SDK
Create the credential with `POST /credentials`. ModuleX detects the credential type from the body: an `auth_data.api_key` value is stored as an `api_key` credential. Set `make_default: true` to make this the default Anthropic credential for the organization.
Every request authenticates with `Authorization: Bearer mx_live_…` plus the `X-Organization-ID` header (see [authentication](/api-reference/authentication)).
```bash cURL
curl -X POST https://api.modulex.dev/credentials \
-H "Authorization: Bearer mx_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Organization-ID: 6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "anthropic",
"display_name": "Anthropic production key",
"make_default": true,
"auth_data": { "api_key": "sk-ant-api03-..." }
}'
```
```python Python
import asyncio
from modulex import Modulex
async def main():
async with Modulex(
api_key="mx_live_xxxxxxxxxxxxxxxxxxxxxxxx", # or MODULEX_API_KEY
organization_id="6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
) as client:
cred = await client.credentials.create(
integration_name="anthropic",
display_name="Anthropic production key",
make_default=True,
auth_data={"api_key": "sk-ant-api03-..."},
)
print(cred.id)
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_xxxxxxxxxxxxxxxxxxxxxxxx", // or process.env.MODULEX_API_KEY
organizationId: "6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
});
const cred = await client.credentials.create({
integration_name: "anthropic",
display_name: "Anthropic production key",
make_default: true,
auth_data: { api_key: "sk-ant-api03-..." },
});
console.log(cred.id);
```
The new credential's identifier. A `201` response returns the credential metadata; the secret is never echoed back.
Creating, listing, and managing credentials and the integration catalog requires the **owner** or **admin** role in the organization. A caller without that role receives a `403`. The integration-catalog read routes (for example `GET /integrations/llm-providers/anthropic`) are also owner/admin-gated.
### Test a key before saving
Use `POST /credentials/test-temporary` to validate an Anthropic key without storing it. ModuleX runs the provider's test call — a 10-token `POST` to `https://api.anthropic.com/v1/messages` against `claude-haiku-4-5-20251001` with the header `anthropic-version: 2023-06-01` — and reports success when the response status is `200` and includes the fields `id`, `type`, and `content`.
```bash cURL
curl -X POST https://api.modulex.dev/credentials/test-temporary \
-H "Authorization: Bearer mx_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Organization-ID: 6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "anthropic",
"auth_type": "api_key",
"auth_data": { "api_key": "sk-ant-api03-..." }
}'
```
```python Python
result = await client.credentials.test_temporary(
integration_name="anthropic",
auth_type="api_key",
auth_data={"api_key": "sk-ant-api03-..."},
)
print(result.is_valid, result.status_code)
```
```javascript JavaScript
const result = await client.credentials.testTemporary({
integration_name: "anthropic",
auth_type: "api_key",
auth_data: { api_key: "sk-ant-api03-..." },
});
console.log(result.is_valid, result.status_code);
```
`true` when the test call succeeds.
The HTTP status returned by Anthropic's test endpoint (`200` on success).
How the credential was validated. For Anthropic this is `api_call`.
The cost class of the test call. For Anthropic this is `minimal` (a 10-token request).
## Available models
ModuleX serves Claude models from the catalog at `GET /integrations/llm-providers/anthropic`. The catalog is read-only metadata used by the credential UI and the builder — it is not the execution path. The models below are the ones ModuleX currently advertises for Anthropic.
| Model id | Display name | Max input tokens | Max output tokens | Vision | Input $/1M | Output $/1M |
| --- | --- | --- | --- | --- | --- | --- |
| `claude-opus-4.7` | Claude Opus 4.7 | 1,000,000 | 128,000 | Yes | `$5.00` | `$25.00` |
| `claude-sonnet-4.6` | Claude Sonnet 4.6 | 200,000 | 64,000 | Yes | `$3.00` | `$15.00` |
| `claude-haiku-4.5` | Claude Haiku 4.5 | 200,000 | 64,000 | Yes | `$1.00` | `$5.00` |
Prices in the table are **Anthropic's per-token rates** as recorded in the ModuleX catalog, in USD per 1,000,000 tokens. Because Anthropic is BYOK, these are the rates Anthropic charges you directly — they are not ModuleX credits. See [BYOK billing](#byok-billing).
Each model id is the catalog id you select in the app and in node configuration. ModuleX maps the catalog id to the underlying Anthropic wire model and request settings:
`claude-opus-4.7` — the catalog id you select.
`Claude Opus 4.7`
`Anthropic`
`anthropic` — the routing provider slug.
`1000000`
`128000`
`true`
`5` (quality score, 1–5).
`1` (latency score, 1–5; higher is faster).
`2026-01-01` (knowledge cutoff).
`5.0`
`25.0`
ModuleX sends the wire model `claude-opus-4-7` with `max_tokens: 128000` and the header `anthropic-version: 2023-06-01`.
`claude-sonnet-4.6`
`Claude Sonnet 4.6`
`anthropic`
`200000`
`64000`
`true`
`4`
`3`
`2026-01-01`
`3.0`
`15.0`
Wire model `claude-sonnet-4-6` with `max_tokens: 64000` and `anthropic-version: 2023-06-01`.
`claude-haiku-4.5`
`Claude Haiku 4.5`
`anthropic`
`200000`
`64000`
`true`
`2`
`5` (fastest).
`2025-07-01`
`1.0`
`5.0`
Wire model `claude-haiku-4-5-20251001` with `max_tokens: 64000` and `anthropic-version: 2023-06-01`. This is the model ModuleX uses for the connection test.
The model list is served from the ModuleX catalog and may change as Anthropic releases or deprecates models. Always read `GET /integrations/llm-providers/anthropic` for the current set rather than hard-coding ids. Catalog reads are cached for up to 10 minutes.
### Read the model catalog
```bash cURL
curl https://api.modulex.dev/integrations/llm-providers/anthropic \
-H "Authorization: Bearer mx_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Organization-ID: 6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f"
```
```python Python
detail = await client.integrations.llm_provider_detail("anthropic")
for model in detail.models:
print(model["id"], model["display_name"])
```
```javascript JavaScript
const detail = await client.integrations.llmProvider("anthropic");
for (const model of detail.models) {
console.log(model.id, model.display_name);
}
```
The response is an integration-detail object whose `models` array contains the entries shown above, plus an `auth_schemas` array describing the `api_key` scheme. A truncated example:
```json Catalog detail (truncated)
{
"name": "anthropic",
"display_name": "Anthropic",
"description": "Anthropic's Claude models for advanced reasoning and long-context tasks",
"integration_type": "llm_provider",
"version": "1.0.0",
"categories": ["AI & LLM Providers", "ai", "chat", "reasoning"],
"auth_schemas": [
{
"auth_type": "api_key",
"display_name": "API Key Authentication",
"description": "Connect using Anthropic API Key"
}
],
"models": [
{
"id": "claude-opus-4.7",
"display_name": "Claude Opus 4.7",
"max_input_tokens": 1000000,
"max_output_tokens": 128000,
"supports_vision": true,
"input_usd_per_1m_tokens": 5.0,
"output_usd_per_1m_tokens": 25.0
}
]
}
```
## Use Claude in ModuleX
Once Anthropic is connected, select a Claude model id wherever a model can be chosen:
Call Claude with prompts, variables, and structured output inside a workflow.
Run an autonomous step where Claude can call tools and loop.
Pick Claude as the model for a chat conversation.
Configure the Assistant to reason and act with a Claude model.
If your organization holds more than one Anthropic credential, ModuleX uses the credential marked default for the `anthropic` integration. Set a different default with `POST /credentials/{credential_id}/set-default`. See [managing credentials](/integrations/managing-credentials).
## BYOK billing
Anthropic is **bring-your-own-key**, which changes how usage is billed compared with [ModuleX-managed models](/integrations/llm-providers/modulexai).
Token usage is billed by **Anthropic** against your own API key. ModuleX adds **no credit charge and no markup** for the model call itself. BYOK usage is recorded for analytics only — it does not consume ModuleX [credits](/billing/credits).
ModuleX provisions the model and bills it in **credits** through the [usage gate](/billing/usage-gating), applying a system margin. Use this when you do not want to manage a provider account.
What this means in practice:
- **No ModuleX credit cost for tokens.** A Claude call made with your Anthropic key is not metered in credits. Anthropic invoices you directly at its own rates (the per-million-token prices in the [model table](#available-models)).
- **Other ModuleX usage still applies.** Running a workflow or a turn through the Assistant can still consume the flat per-run credit and may pass through the billing gate even when the model itself is BYOK. See [credits & metering](/billing/credits) and [usage gating & limits](/billing/usage-gating).
- **Rate limits and quotas are Anthropic's.** Token-rate limits, monthly spend caps, and model availability for a BYOK key are governed by your Anthropic account, not by ModuleX.
BYOK is available on all plans — there is no separate ModuleX entitlement that gates connecting your own Anthropic key. The pricing matrix on the marketing site lists BYOK for every tier; the only ModuleX-side billing that applies to a BYOK call is the non-model usage described above. **TBD:** confirm with the billing owner that no per-call ModuleX surcharge applies to BYOK model calls before treating "no markup" as a guarantee.
## Errors
Catalog and credential operations return ModuleX's standard error shapes. See [errors & status codes](/api-reference/errors) for the full taxonomy.
| Status | When it happens | Shape |
| --- | --- | --- |
| `400` | Invalid `auth_data`/`auth_type` on credential create, or asking a typed endpoint for the wrong integration type (for example `anthropic` is not a tool). | `{detail: string}` |
| `401` | Missing or invalid `Authorization` / missing `X-Organization-ID`. | `{detail: string}` |
| `403` | Caller is not an owner/admin in the organization. | `{detail: string}` |
| `404` | Unknown provider, for example `GET /integrations/llm-providers/` returns `LLM provider not found`. | `{detail: string}` |
| `422` | Query/parameter validation error. | `{detail: [ ... ]}` |
| `500` | Unhandled server error. | `{detail: string}` |
A bad Anthropic key does not surface as a ModuleX `401`. Connection validation happens against Anthropic: `POST /credentials/test-temporary` (or saving with validation) returns `is_valid: false` with the status Anthropic returned (for example `401` from `api.anthropic.com`). The ModuleX request itself still succeeds.
## Related
All providers, and how managed vs BYOK selection works.
The credit-billed managed alternative to BYOK.
How integrations authenticate and the auth schema variants.
Create, default, rotate, and scope credentials.
---
# Google Gemini models
URL: https://docs.modulex.dev/integrations/llm-providers/gemini
Connect Google Gemini to ModuleX with your own API key, browse the available Gemini models, and understand how BYOK usage is billed.
Google Gemini is a [BYOK (bring-your-own-key)](/reference/glossary) LLM provider in ModuleX. You connect your own Google AI API key, then use Gemini models in the [LLM node](/workflow-builder/nodes/llm), the [Agent node](/workflow-builder/nodes/agent), [chat](/platform/chat/model-selection), and the [Assistant](/assistant/models-and-settings). Because Gemini is BYOK, Google bills you directly for token usage and ModuleX adds no credit charge on top — see [BYOK billing](#byok-billing) below.
For the full list of provider types and how managed versus BYOK selection works, see [LLM providers](/integrations/llm-providers/overview). If you would rather have ModuleX provision and meter the model for you in credits, use [ModuleX-managed models](/integrations/llm-providers/modulexai) instead.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4080 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The Google Gemini connection card in the ModuleX integrations/credentials UI.
**[SCREENSHOT_DETAILS]:** Capture the API Key Authentication form for Gemini in the credential-management UI: the `API Key` field (masked), the optional `Base URL` field defaulted to `https://generativelanguage.googleapis.com/v1beta`, and the "Test connection" / "Save" controls. Light theme, 16:9, crop to the card.
## What you need
Create a key in [Google AI Studio](https://aistudio.google.com/app/apikey): click **Create API Key**, select (or create) a Google Cloud project, then copy the key. Google AI keys start with `AIza` (for example `AIzaSy…`). ModuleX validates the key against the pattern `^AIza[0-9A-Za-z\-_]{35}$` before saving it.
Credentials are scoped to an [organization](/concepts/organizations-roles). Connecting and managing integrations requires the **owner** or **admin** role — the `member` role is retired. See [roles & permissions](/security/roles-permissions).
To connect Gemini over the API or an SDK, you need a ModuleX API key (`mx_live_…`) and your organization id. See [authentication](/api-reference/authentication).
## Connect Gemini
You connect Gemini by storing your Google AI API key as a [credential](/integrations/managing-credentials) for the `gemini` integration. You can do this in the app or programmatically.
### In the app
1. Open the [integrations catalog](/integrations/catalog) and select **Gemini**, or open **Settings → Credentials**.
2. Choose **API Key Authentication** and paste your Google AI key.
3. Optionally set a custom **Base URL** (defaults to `https://generativelanguage.googleapis.com/v1beta`) — only needed for Google AI-compatible gateways.
4. Save. ModuleX validates the key with a minimal request before storing it (see [Test a key before saving](#test-a-key-before-saving)).
Gemini exposes a single authentication scheme — `api_key`. Its fields are:
Your Google AI API key. Stored encrypted and never returned in plaintext. Marked `sensitive`. Pattern `^AIza[0-9A-Za-z\-_]{35}$`; sample format `AIzaSyXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`.
Optional custom API base URL, only needed when pointing at a Google AI-compatible API. Not required and not sensitive. Must match `^https?://.*`.
### Over the API or an SDK
Create the credential with `POST /credentials`. ModuleX detects the credential type from the body: an `auth_data.api_key` value is stored as an `api_key` credential. Set `make_default: true` to make this the default Gemini credential for the organization.
Every request authenticates with `Authorization: Bearer mx_live_…` plus the `X-Organization-ID` header (see [authentication](/api-reference/authentication)).
```bash cURL
curl -X POST https://api.modulex.dev/credentials \
-H "Authorization: Bearer mx_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Organization-ID: 6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "gemini",
"display_name": "Gemini production key",
"make_default": true,
"auth_data": { "api_key": "AIzaSy..." }
}'
```
```python Python
import asyncio
from modulex import Modulex
async def main():
async with Modulex(
api_key="mx_live_xxxxxxxxxxxxxxxxxxxxxxxx", # or MODULEX_API_KEY
organization_id="6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
) as client:
cred = await client.credentials.create(
integration_name="gemini",
display_name="Gemini production key",
make_default=True,
auth_data={"api_key": "AIzaSy..."},
)
print(cred.id)
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_xxxxxxxxxxxxxxxxxxxxxxxx", // or process.env.MODULEX_API_KEY
organizationId: "6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
});
const cred = await client.credentials.create({
integration_name: "gemini",
display_name: "Gemini production key",
make_default: true,
auth_data: { api_key: "AIzaSy..." },
});
console.log(cred.id);
```
The new credential's identifier. A `201` response returns the credential metadata; the secret is never echoed back.
Creating, listing, and managing credentials and the integration catalog requires the **owner** or **admin** role in the organization. A caller without that role receives a `403`. The integration-catalog read routes (for example `GET /integrations/llm-providers/gemini`) are also owner/admin-gated.
### Test a key before saving
Use `POST /credentials/test-temporary` to validate a Gemini key without storing it. ModuleX runs the provider's test call — a 10-token `POST` to `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-lite:generateContent` with the header `x-goog-api-key` set to your key — and reports success when the response status is `200` and includes a `candidates` field.
```bash cURL
curl -X POST https://api.modulex.dev/credentials/test-temporary \
-H "Authorization: Bearer mx_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Organization-ID: 6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "gemini",
"auth_type": "api_key",
"auth_data": { "api_key": "AIzaSy..." }
}'
```
```python Python
result = await client.credentials.test_temporary(
integration_name="gemini",
auth_type="api_key",
auth_data={"api_key": "AIzaSy..."},
)
print(result.is_valid, result.status_code)
```
```javascript JavaScript
const result = await client.credentials.testTemporary({
integration_name: "gemini",
auth_type: "api_key",
auth_data: { api_key: "AIzaSy..." },
});
console.log(result.is_valid, result.status_code);
```
`true` when the test call succeeds.
The HTTP status returned by Google's test endpoint (`200` on success).
How the credential was validated. For Gemini this is `api_call`.
The cost class of the test call. For Gemini this is `minimal` (a 10-token request).
## Available models
ModuleX serves Gemini models from the catalog at `GET /integrations/llm-providers/gemini`. The catalog is read-only metadata used by the credential UI and the builder — it is not the execution path. The models below are the ones ModuleX currently advertises for Gemini. Every Gemini model supports vision (image input) and a 1,048,576-token context window.
| Model id | Display name | Max input tokens | Max output tokens | Vision | Input $/1M | Output $/1M |
| --- | --- | --- | --- | --- | --- | --- |
| `gemini-2.5-pro` | Gemini 2.5 Pro | 1,048,576 | 65,536 | Yes | `$2.50` | `$15.00` |
| `gemini-2.5-flash` | Gemini 2.5 Flash | 1,048,576 | 65,536 | Yes | `$0.30` | `$2.50` |
| `gemini-2.5-flash-lite` | Gemini 2.5 Flash Lite | 1,048,576 | 65,536 | Yes | `$0.10` | `$0.40` |
Prices in the table are **Google's per-token rates** as recorded in the ModuleX catalog, in USD per 1,000,000 tokens. Because Gemini is BYOK, these are the rates Google charges you directly — they are not ModuleX credits. See [BYOK billing](#byok-billing).
Each model id is the catalog id you select in the app and in node configuration. ModuleX maps the catalog id to the underlying Gemini wire model and request settings:
`gemini-2.5-pro` — the catalog id you select.
`Gemini 2.5 Pro`
`Gemini`
`gemini` — the routing provider slug.
`1048576`
`65536`
`true`
`5` (quality score, 1–5).
`2` (latency score, 1–5; higher is faster).
`2025-01-01` (knowledge cutoff).
`2.5`
`15.0`
ModuleX sends the wire model `gemini-2.5-pro` (the `body_extra.model` value). No extra headers are set (`headers_extra` is empty).
`gemini-2.5-flash`
`Gemini 2.5 Flash`
`gemini`
`1048576`
`65536`
`true`
`3`
`3`
`2025-01-01`
`0.3`
`2.5`
Wire model `gemini-2.5-flash` (the `body_extra.model` value); no extra headers.
`gemini-2.5-flash-lite`
`Gemini 2.5 Flash Lite`
`gemini`
`1048576`
`65536`
`true`
`2`
`4`
`2025-01-01`
`0.1`
`0.4`
Wire model `gemini-2.5-flash-lite` (the `body_extra.model` value); no extra headers.
The catalog `max_output_tokens` is the model's hard ceiling. Separately, ModuleX applies a per-scenario output cap that is **lower** than the model ceiling and is **not** exposed through any catalog API response — for every Gemini model it is `8000` for simple chat, `10000` for chat with knowledge, `4000` for an LLM node, `12000` for an Agent node, `32000` for the main Composer agent, and `4000` for a Composer subagent. These caps are internal defaults and may change.
The model list is served from the ModuleX catalog and may change as Google releases or deprecates models. Always read `GET /integrations/llm-providers/gemini` for the current set rather than hard-coding ids. Catalog reads are cached for up to 10 minutes.
### Read the model catalog
```bash cURL
curl https://api.modulex.dev/integrations/llm-providers/gemini \
-H "Authorization: Bearer mx_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Organization-ID: 6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f"
```
```python Python
detail = await client.integrations.llm_provider_detail("gemini")
for model in detail.models:
print(model["id"], model["display_name"])
```
```javascript JavaScript
const detail = await client.integrations.llmProvider("gemini");
for (const model of detail.models) {
console.log(model.id, model.display_name);
}
```
The response is an integration-detail object whose `models` array contains the entries shown above, plus an `auth_schemas` array describing the `api_key` scheme. A truncated example:
```json Catalog detail (truncated)
{
"name": "gemini",
"display_name": "Gemini",
"description": "Google's Gemini models for advanced reasoning, multimodal tasks, and long-context processing",
"integration_type": "llm_provider",
"version": "1.0.0",
"categories": ["AI & LLM Providers", "ai", "chat", "reasoning", "multimodal"],
"auth_schemas": [
{
"auth_type": "api_key",
"display_name": "API Key Authentication",
"description": "Connect using Google AI API Key"
}
],
"models": [
{
"id": "gemini-2.5-pro",
"display_name": "Gemini 2.5 Pro",
"provider_id": "gemini",
"max_input_tokens": 1048576,
"max_output_tokens": 65536,
"supports_vision": true,
"input_usd_per_1m_tokens": 2.5,
"output_usd_per_1m_tokens": 15.0
}
]
}
```
## Use Gemini in ModuleX
Once Gemini is connected, select a Gemini model id wherever a model can be chosen:
Call Gemini with prompts, variables, and structured output inside a workflow.
Run an autonomous step where Gemini can call tools and loop.
Pick Gemini as the model for a chat conversation.
Configure the Assistant to reason and act with a Gemini model.
If your organization holds more than one Gemini credential, ModuleX uses the credential marked default for the `gemini` integration. Set a different default with `POST /credentials/{credential_id}/set-default`. See [managing credentials](/integrations/managing-credentials).
## BYOK billing
Gemini is **bring-your-own-key**, which changes how usage is billed compared with [ModuleX-managed models](/integrations/llm-providers/modulexai).
Token usage is billed by **Google** against your own API key. ModuleX adds **no credit charge and no markup** for the model call itself. BYOK usage is recorded for analytics only — it does not consume ModuleX [credits](/billing/credits).
ModuleX provisions the model and bills it in **credits** through the [usage gate](/billing/usage-gating), applying a system margin. Use this when you do not want to manage a provider account.
What this means in practice:
- **No ModuleX credit cost for tokens.** A Gemini call made with your Google AI key is not metered in credits. Google invoices you directly at its own rates (the per-million-token prices in the [model table](#available-models)).
- **Other ModuleX usage still applies.** Running a workflow or a turn through the Assistant can still consume the flat per-run credit and may pass through the billing gate even when the model itself is BYOK. See [credits & metering](/billing/credits) and [usage gating & limits](/billing/usage-gating).
- **Rate limits and quotas are Google's.** Token-rate limits, monthly spend caps, and model availability for a BYOK key are governed by your Google AI account, not by ModuleX.
BYOK is available on all plans — there is no separate ModuleX entitlement that gates connecting your own Gemini key. The pricing matrix on the marketing site lists BYOK for every tier; the only ModuleX-side billing that applies to a BYOK call is the non-model usage described above. **TBD:** confirm with the billing owner that no per-call ModuleX surcharge applies to BYOK model calls before treating "no markup" as a guarantee.
## Errors
Catalog and credential operations return ModuleX's standard error shapes. See [errors & status codes](/api-reference/errors) for the full taxonomy.
| Status | When it happens | Shape |
| --- | --- | --- |
| `400` | Invalid `auth_data`/`auth_type` on credential create, or asking a typed endpoint for the wrong integration type (for example `gemini` is not a tool). | `{detail: string}` |
| `401` | Missing or invalid `Authorization` / missing `X-Organization-ID`. | `{detail: string}` |
| `403` | Caller is not an owner/admin in the organization. | `{detail: string}` |
| `404` | Unknown provider, for example `GET /integrations/llm-providers/` returns `LLM provider not found`. | `{detail: string}` |
| `422` | Query/parameter validation error. | `{detail: [ ... ]}` |
| `500` | Unhandled server error. | `{detail: string}` |
A bad Gemini key does not surface as a ModuleX `401`. Connection validation happens against Google: `POST /credentials/test-temporary` (or saving with validation) returns `is_valid: false` with the status Google returned (for example `400` from `generativelanguage.googleapis.com` for an invalid key). The ModuleX request itself still succeeds.
## Related
All providers, and how managed vs BYOK selection works.
The credit-billed managed alternative to BYOK.
How integrations authenticate and the auth schema variants.
Create, default, rotate, and scope credentials.
---
# ModuleX-managed models
URL: https://docs.modulex.dev/integrations/llm-providers/modulexai
Use ModuleX-managed models (modulexai) — the default LLM provider that needs no API key, ships curated models, and is metered in credits. Includes the full model catalog, credit-cost formula, and how to switch to BYOK.
`modulexai` is the **ModuleX-managed model** provider — the default option for every surface that calls a language model. You do not supply or manage any provider key: ModuleX provisions the upstream keys for you and meters usage in [credits](/billing/credits) against your plan allowance and [wallet](/billing/wallet). Managed models are available out of the box on the [Chat model selector](/platform/chat/model-selection), the [Assistant](/assistant/models-and-settings), the [LLM node](/workflow-builder/nodes/llm), the [Agent node](/workflow-builder/nodes/agent), and the [AI Composer](/concepts/ai-composer).
The alternative is [BYOK (bring your own key)](/integrations/llm-providers/overview): you connect a first-party provider account and that vendor bills you directly, with no ModuleX credit charge. This page covers managed models end to end — the auth model, the curated catalog, exactly what each call costs in credits, and how to switch a selection to BYOK. For how managed-versus-BYOK selection works across all providers, see [Connect LLM providers](/integrations/llm-providers/overview).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4100 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The ModuleX-managed (`modulexai`) entry in the model selector.
**[SCREENSHOT_DETAILS]:** Capture the model picker in chat (or Assistant settings) showing the ModuleX-managed models grouped together — for example `Claude Sonnet 4.6`, `GPT 5.5`, `Claude Opus 4.6` — with no API-key/connect prompt, signalling they are ready to use. Light theme, 16:9, crop to the dropdown.
## How managed models work
A managed model is one whose provider wire name is `modulexai`. When you pick such a model, the request runs through ModuleX-provisioned upstream keys and the call is **costed in credits**:
Choose a `modulexai` model id (for example `claude-sonnet-4.6` or `gpt-5.5`) anywhere a model can be picked. No credential is required — `modulexai` is exempt from credential validation because it uses ModuleX's own model-level keys.
ModuleX maps the model id to its upstream wire model and request settings. Several managed models are routed through an aggregator with a Bedrock-then-Anthropic fallback order; you select by ModuleX `model_id` and the routing is handled for you. Deprecated ids are resolved to their replacement automatically — see [Deprecated models route automatically](#deprecated-models-route-automatically).
Every managed turn passes through the [usage gate](/billing/usage-gating): it reserves credit before any work, charges on success, and denies with a [`DenialEnvelope`](/api-reference/errors) on `402` / `403` / `429` when your allowance and wallet are exhausted. See [Credit cost](#credit-cost).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4101 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** Request path for a managed (`modulexai`) model call versus a BYOK call.
**[IMAGE_DETAILS]:** Show two lanes from a single "model call" box. Managed lane: ModuleX-provisioned key, routed through the aggregator, passing the credit usage gate (reserve to charge to settle) and metered in credits. BYOK lane: your own credential, routed straight to the upstream vendor, billed by the vendor, not credited. Label which lane consumes credits. 16:9, light and dark variants, ModuleX brand palette, no UI chrome.
### No key required: the `modulex_key` auth schema
Managed access uses a single auth schema, `modulex_key`. Unlike BYOK providers, it has **no fields for you to fill in** — its `setup_environment_variables` array is empty. ModuleX supplies the upstream key automatically and tracks usage against your subscription plan's monthly credit allowance.
`modulex_key` — the managed-key scheme. ModuleX provides the API keys automatically; no key configuration is needed.
`ModuleX Managed Key`.
Empty (`[]`). There is nothing to enter to use managed models.
Because `modulexai` needs no credential, you do **not** call `POST /credentials` for it. Managed models are usable as soon as your organization is on any plan (Free included). You still need to be an [owner or admin](/security/roles-permissions) to manage the integration catalog or change defaults; the `member` role is retired.
## Available models
ModuleX serves the managed model list from the catalog at `GET /integrations/llm-providers/modulexai`. The catalog is **read-only metadata** used by the model selectors and the builder — it is not the execution path, and it never returns or stores a secret key. The catalog read is cached for up to 10 minutes.
The active models below are the ones ModuleX currently advertises for `modulexai`. There are six deprecated `bedrock-*` ids in addition; see [Deprecated models](#deprecated-models).
### Chat and reasoning models
| Model id | Display name | Upstream | Max input | Max output | Vision | Input `$/1M` | Output `$/1M` |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `claude-sonnet-4.6` | Claude Sonnet 4.6 | Anthropic | 200,000 | 64,000 | Yes | `$3.00` | `$15.00` |
| `claude-opus-4.6` | Claude Opus 4.6 | Anthropic | 200,000 | 128,000 | Yes | `$5.00` | `$25.00` |
| `claude-haiku-4.5` | Claude Haiku 4.5 | Anthropic | 200,000 | 64,000 | Yes | `$0.80` | `$4.00` |
| `gpt-5.5` | GPT 5.5 | OpenAI | 1,050,000 | 128,000 | Yes | `$5.00` | `$30.00` |
| `gpt-5.4` | GPT 5.4 | OpenAI | 1,050,000 | 128,000 | Yes | `$2.50` | `$15.00` |
| `gpt-5.4-mini` | GPT 5.4 mini | OpenAI | 400,000 | 128,000 | Yes | `$0.75` | `$4.50` |
| `gpt-5.4-nano` | GPT 5 nano | OpenAI | 400,000 | 128,000 | Yes | `$0.20` | `$1.25` |
| `gpt-5-chat-latest` | GPT 5 chat latest | OpenAI | 128,000 | 16,384 | Yes | `$1.25` | `$10.00` |
| `gpt-5.3-codex` | GPT 5.3 codex | OpenAI | 400,000 | 128,000 | Yes | `$1.75` | `$14.00` |
| `o3` | o3 | OpenAI | 200,000 | 100,000 | Yes | `$2.00` | `$8.00` |
| `gemma-3-27b` | Gemma 3 27B | Google | 128,000 | 8,192 | Yes | `$0.10` | `$0.10` |
| `gemma-3-12b` | Gemma 3 12B | Google | 128,000 | 8,192 | Yes | `$0.05` | `$0.05` |
| `gemma-3-4b` | Gemma 3 4B | Google | 128,000 | 8,192 | No | `$0.02` | `$0.02` |
### Embedding models
| Model id | Display name | Upstream | Max input | Dimensions | Input `$/1M` | Output `$/1M` |
| --- | --- | --- | --- | --- | --- | --- |
| `text-embedding-3-large` | Text Embedding 3 Large | OpenAI | 8,191 | 3,072 | `$0.13` | `$0.00` |
| `text-embedding-3-small` | Text Embedding 3 Small | OpenAI | 8,191 | 1,536 | `$0.02` | `$0.00` |
The per-million-token prices above are the **upstream provider's USD rates** recorded in the ModuleX catalog. For managed (`modulexai`) usage they are **inputs to the credit-cost formula**, not amounts you pay directly — your actual charge is in [credits](/billing/credits) and includes a 5% system margin. See [Credit cost](#credit-cost). Embedding models report a zero output price because embedding forces `completion_tokens = 0`.
The model list is served from the catalog and changes as ModuleX adds, routes, or deprecates models. Read `GET /integrations/llm-providers/modulexai` for the current set rather than hard-coding ids; catalog reads are cached for up to 10 minutes.
### The model record
Each entry in the provider's `models[]` array carries the fields below.
The ModuleX `model_id` you select (for example `claude-sonnet-4.6`).
Human-readable name shown in selectors.
Display vendor — `Anthropic`, `OpenAI`, or `Google` on active managed models.
Routing provider slug. Managed chat/reasoning models route through `openrouter`; the OpenAI embedding models route through `openai`.
Maximum context window in tokens.
Maximum tokens the model can generate. `0` for embedding models.
Knowledge-cutoff date (for example `2026-01-01`). This field, not a `knowledge_cutoff` key, carries the cutoff.
Quality score, 1–5.
Latency score, 1–5 (higher is faster).
Whether the model accepts image input.
Upstream input price per 1M tokens, as a flat number (not a nested `pricing` object).
Upstream output price per 1M tokens. `0.0` on embedding models.
`true` on the two embedding models. Embedding models also report `embedding_dimension` and a zero output price.
Vector dimension for embedding models (`3072` for `text-embedding-3-large`, `1536` for `text-embedding-3-small`).
Lifecycle state. Present and set to `deprecated` on the retired `bedrock-*` ids; active models omit it (treated as healthy).
On a deprecated model, the successor `model_id` ModuleX routes the call to instead.
```json
{
"id": "claude-sonnet-4.6",
"display_name": "Claude Sonnet 4.6",
"provider": "Anthropic",
"provider_id": "openrouter",
"max_input_tokens": 200000,
"max_output_tokens": 64000,
"data_freshness": "2026-01-01",
"intelligence": 4,
"speed": 3,
"supports_vision": true,
"input_usd_per_1m_tokens": 3.0,
"output_usd_per_1m_tokens": 15.0
}
```
### Read the model catalog
```bash cURL
curl https://api.modulex.dev/integrations/llm-providers/modulexai \
-H "Authorization: Bearer mx_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Organization-ID: 6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f"
```
```python Python
import asyncio
from modulex import Modulex
async def main():
async with Modulex(
api_key="mx_live_xxxxxxxxxxxxxxxxxxxxxxxx", # or MODULEX_API_KEY
organization_id="6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
) as client:
detail = await client.integrations.llm_provider_detail("modulexai")
for model in detail.models:
print(model["id"], model["display_name"])
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_xxxxxxxxxxxxxxxxxxxxxxxx", // or process.env.MODULEX_API_KEY
organizationId: "6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
});
const detail = await client.integrations.llmProvider("modulexai");
for (const model of detail.models) {
console.log(model.id, model.display_name);
}
```
The response is an integration-detail object whose `models` array contains the entries above plus an `auth_schemas` array describing the single `modulex_key` scheme. A truncated example:
```json Catalog detail (truncated)
{
"name": "modulexai",
"display_name": "ModulexAI",
"description": "ModuleX's managed LLM provider with curated models and usage tracking",
"integration_type": "llm_provider",
"version": "1.0.0",
"categories": ["AI & LLM Providers", "ai", "chat", "managed"],
"auth_schemas": [
{
"auth_type": "modulex_key",
"display_name": "ModuleX Managed Key",
"description": "Use ModuleX's managed API keys with usage tracked against your monthly credit limit",
"setup_environment_variables": []
}
],
"models": [
{
"id": "claude-sonnet-4.6",
"display_name": "Claude Sonnet 4.6",
"max_input_tokens": 200000,
"max_output_tokens": 64000,
"supports_vision": true,
"input_usd_per_1m_tokens": 3.0,
"output_usd_per_1m_tokens": 15.0
}
]
}
```
The catalog detail endpoints are owner/admin-gated and org-scoped: every request needs `Authorization: Bearer mx_live_…` plus `X-Organization-ID`, and the caller must be an owner or admin. See [Authentication](/api-reference/authentication).
## Credit cost
Managed (`modulexai`) usage is the only LLM-provider usage that consumes [credits](/billing/credits). A credit is the managed-usage billing unit: **100 credits = $1.00** (1 credit = `$0.01`). BYOK calls are never credited.
A managed call is metered in two parts.
### Per-turn run charge
Each logical run or chat turn is charged a flat `RUN_CREDIT` of **1** credit, recorded once and deduplicated by an idempotency key so a resumed turn is not double-charged.
### Token metering
The model's tokens are converted to credits using the upstream per-token rates plus a system margin:
```text Token-to-credit formula
cost = (prompt_tokens · input_rate / 1e6 + completion_tokens · output_rate / 1e6) · MARGIN · SCALE
```
where:
| Symbol | Value | Meaning |
| --- | --- | --- |
| `input_rate` / `output_rate` | the model's `input_usd_per_1m_tokens` / `output_usd_per_1m_tokens` | upstream USD rates from the [model record](#the-model-record) |
| `MARGIN` | `1.05` | a 5% system margin applied to managed usage |
| `SCALE` | `100` | `100 credits = $1.00`, so 1 credit = `$0.01` |
Embedding calls force `completion_tokens = 0`, so only input tokens are metered. If a model id is unknown to the pricing table, it meters to `0` rather than a silent fallback rate.
Other managed operations carry their own flat base charges, also billed in credits: a managed **knowledge retrieval** reserves `RETRIEVAL_BASE` = 1 credit, a managed **document ingest** reserves `FILE_INGEST_BASE` = 1 credit, and an **integration tool** call has a `TOOL_BASE` of 1 credit (`$0.01`). These apply to the corresponding managed surfaces, not to a plain LLM call. See [Credits & metering](/billing/credits).
### Worked example
A single `claude-sonnet-4.6` turn that reads 10,000 prompt tokens and writes 1,000 completion tokens:
- Token cost = `(10000 · 3.0 / 1e6 + 1000 · 15.0 / 1e6) · 1.05 · 1000` = `(0.03 + 0.015) · 1.05 · 1000` ≈ **47.25 credits** (≈ `$0.047`).
- Plus the flat per-turn `RUN_CREDIT` of **1** credit.
So the turn costs roughly **48 credits**. The exact charge is quantized to eight decimal places when recorded.
### When a managed call is denied
When managed usage exhausts your plan allowance and wallet, the billing admission gate denies the call with a flat [`DenialEnvelope`](/api-reference/errors) — `{code, layer, key, current, limit, reason}` — returned on:
| Status | `layer` | When |
| --- | --- | --- |
| `402` | `credit` / `wallet` | Plan credits exhausted, overage disabled, or wallet balance insufficient. |
| `403` | `quota` | A plan quota is exceeded. |
| `429` | `rate` | A per-plan rate class (for example `sync_exec`) is exceeded; includes `Retry-After` and `X-RateLimit-*` headers. |
These envelopes appear only on **managed-usage surfaces** — the run, Composer, Assistant, and managed-knowledge calls that actually meter credits. Plain credential and catalog CRUD return the FastAPI `{detail}` `HTTPException` shape instead. See [Errors & status codes](/api-reference/errors) and [Usage gating & limits](/billing/usage-gating).
## Where you select a managed model
A managed model id is selectable anywhere a model is chosen — no connection step:
Pick a managed model in the chat composer.
Set a managed model for the Assistant to reason and act with.
Set `model_id` on the node to a managed id.
Run an autonomous step on a managed model.
### Deprecated models route automatically
When you select a model whose `status` is `deprecated` (or `maintenance`), ModuleX resolves it to its `replacement_id` before the call — for example a `bedrock-claude-sonnet-4.6` id routes to `claude-sonnet-4.6`. Routing is cycle- and depth-guarded, so a chain of replacements terminates at a live model. For a managed integration, if a requested id is unknown or its chain cannot resolve, ModuleX softens to the integration's first serving (healthy, non-deprecated) model rather than failing. You do not need to update saved selections immediately, but prefer a live id for clarity.
#### Deprecated models
These six ids exist only for backward compatibility and route to their replacements. Do not select them for new work.
| Deprecated id | Routes to |
| --- | --- |
| `bedrock-claude-sonnet-4.6` | `claude-sonnet-4.6` |
| `bedrock-claude-opus-4.6` | `claude-opus-4.6` |
| `bedrock-claude-haiku-4.5` | `claude-haiku-4.5` |
| `bedrock-gemma-3-27b` | `gemma-3-27b` |
| `bedrock-gemma-3-12b` | `gemma-3-12b` |
| `bedrock-gemma-3-4b` | `gemma-3-4b` |
## Switching to BYOK
Managed and BYOK are a per-selection choice — you switch by changing which model a surface uses, not by a global toggle. To move a chat, Assistant, or node off managed credits and onto a vendor-direct bill, select a model from a connected BYOK provider instead of a `modulexai` model.
Create a credential for a first-party provider (`openai`, `anthropic`, `gemini`, or `xai`) with `POST /credentials`, supplying your own provider key. You must be an owner or admin. See [Connect LLM providers](/integrations/llm-providers/overview) and the per-provider pages, for example [Anthropic](/integrations/llm-providers/anthropic) and [OpenAI](/integrations/llm-providers/openai).
In the [chat model selector](/platform/chat/model-selection), [Assistant settings](/assistant/models-and-settings), or a node, choose a model from the connected provider in place of the `modulexai` model.
BYOK token usage is billed by the upstream vendor with no ModuleX markup and is recorded for analytics only — it does not consume credits. Non-model ModuleX usage (such as the flat per-run charge, or managed knowledge/tool calls) can still apply.
Switching a model **moves cost between billing systems**. A `modulexai` selection consumes ModuleX credits and is subject to the billing gate; a BYOK selection is billed by your provider and is not credited. Switching back to a `modulexai` model returns that cost to credits. Confirm which model is selected before relying on either path.
All providers, and how managed vs BYOK selection works.
What a credit is and exactly what consumes credits.
## Errors
Catalog reads for `modulexai` return ModuleX's standard error shapes. Managed model **calls** can additionally return the billing `DenialEnvelope` described in [When a managed call is denied](#when-a-managed-call-is-denied).
| Status | When it happens | Shape |
| --- | --- | --- |
| `400` | Asking a typed endpoint for the wrong integration type (for example `modulexai` is not a tool). | `{detail: string}` |
| `401` | Missing or invalid `Authorization`, or missing `X-Organization-ID`. | `{detail: string}` |
| `403` | Caller is not an owner or admin in the organization. | `{detail: string}` |
| `404` | Unknown provider, for example `GET /integrations/llm-providers/` returns `LLM provider not found`. | `{detail: string}` |
| `422` | Query/parameter validation error. | `{detail: [ ... ]}` |
| `402` / `403` / `429` | A managed model call hits the billing gate (credit, quota, or rate). | `DenialEnvelope` — `{code, layer, key, current, limit, reason}` |
| `500` | Unhandled server error. | `{detail: string}` |
See [Errors & status codes](/api-reference/errors) for all three envelope shapes and which surface emits each.
## Related
Managed vs BYOK, and the full provider list.
The credit unit and what consumes credits.
The billing admission gate and its 402/403/429 responses.
The bring-your-own-key alternative for Claude models.
## Open questions (TBD)
- **Upstream routing detail.** Several managed models route through an aggregator (`openrouter`) with a Bedrock-then-Anthropic fallback order, and the OpenAI embedding models route through `openai`. The exact upstream selected for a given call is handled internally and is not exposed in any catalog API response; treat the routing as an implementation detail subject to change.
- **Public catalog base URL.** The catalog and SDK examples use `https://api.modulex.dev` per the repo-wide convention; the exact public host for these endpoints is not pinned from source and should be confirmed against the deployed environment.
- **Per-model max-output overrides.** ModuleX applies scenario-specific maximum-output-token limits to managed calls (for example a smaller cap for simple chat than for an agent step). These limits are backend-only and are never returned in a catalog response, so the catalog's `max_output_tokens` is the model ceiling, not necessarily the per-scenario limit applied at run time.
---
# OpenAI
URL: https://docs.modulex.dev/integrations/llm-providers/openai
Connect your OpenAI account to ModuleX, browse the GPT, o-series, and embedding models in the catalog, select them in workflows, the Assistant, and chat, and understand BYOK billing.
OpenAI is a **bring-your-own-key (BYOK) LLM provider** in ModuleX. You connect your own OpenAI API key as a [credential](/concepts/credentials-oauth), and ModuleX uses it to call OpenAI's GPT, o-series reasoning, and embedding models from your [workflows](/concepts/workflows-and-runs), the [Assistant](/concepts/assistant), the [AI Composer](/concepts/ai-composer), and [chat](/platform/chat/overview). Because OpenAI usage runs through your own key, it is **billed by OpenAI directly** and consumes **no ModuleX [credits](/concepts/credits-billing)**.
This page covers connecting an OpenAI credential, the OpenAI models ModuleX exposes in its catalog, how to select an OpenAI model on each surface, and how BYOK billing works. For the cross-provider picture see [LLM providers](/integrations/llm-providers/overview); for the credential model and OAuth see [Credentials & OAuth2](/concepts/credentials-oauth).
OpenAI is the integration named `openai` on the wire (`integration_type: "llm_provider"`). It exposes **one auth schema** — `api_key` — so there is no ModuleX-managed (pooled-key) option for OpenAI. For credit-metered managed models, use [ModuleX-managed models](/integrations/llm-providers/modulexai) instead.
## Before you start
Create a secret key at the [OpenAI API keys page](https://platform.openai.com/api-keys). It starts with `sk-` (for example `sk-proj-…`). ModuleX validates it against the format `^sk-[a-zA-Z0-9\-_]{20,}$`.
Creating and managing credentials and browsing the integration catalog require the **owner** or **admin** role in your [organization](/concepts/organizations-roles). The retired `member` role cannot perform these actions. See [Roles & permissions](/security/roles-permissions).
Every API call sends `Authorization: Bearer mx_live_…` and `X-Organization-ID`. See [Authentication](/api-reference/authentication).
BYOK usage is charged by OpenAI to your OpenAI account, not by ModuleX. Make sure your OpenAI account has billing enabled and sufficient quota.
## Connect OpenAI
You connect OpenAI by creating an `api_key` [credential](/concepts/credentials-oauth) for the `openai` integration. ModuleX auto-detects the credential type from the body you send: an `auth_data` object containing `api_key` is stored as an `api_key` credential.
In the OpenAI dashboard, go to [API keys](https://platform.openai.com/api-keys), choose **Create new secret key**, name it, set its permissions, and copy the value. You only see it once — store it securely until you paste it into ModuleX.
Call `POST /credentials/test-temporary` to check the key works **before** persisting it. ModuleX runs OpenAI's configured test — a minimal `POST https://api.openai.com/v1/chat/completions` with `gpt-5.4-mini` and `max_tokens: 10` — and reports `is_valid`.
Call `POST /credentials` with `integration_name: "openai"` and `auth_data.api_key`. Set `make_default: true` to make it the default OpenAI credential for the organization. ModuleX encrypts the key at rest and never returns it in clear text.
The key is now resolvable for any surface that runs an OpenAI model — workflows, the Assistant, the Composer, and chat. See [Select an OpenAI model](#select-an-openai-model).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4060 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The ModuleX app credential dialog for connecting OpenAI with an API key.
**[SCREENSHOT_DETAILS]:** Capture the "Connect OpenAI" credential form in the integrations/credentials area of the ModuleX app. Show the OpenAI logo, the API Key field (masked, placeholder `sk-proj-…`), the optional Base URL field defaulting to `https://api.openai.com/v1`, the "Set as default" toggle, and the Test/Save buttons. Light theme, 16:9, crop to the dialog.
### Create the credential
`POST /credentials` returns `201`. The type is auto-detected from the body — passing `auth_data.api_key` yields an `api_key` credential. See the full credentials reference in [Credentials & OAuth2](/concepts/credentials-oauth).
Must be `openai`.
The secret material. For OpenAI, `{"api_key": "sk-proj-…"}`. The presence of `api_key` selects the `api_key` auth type. To target an OpenAI-compatible endpoint, also include `base_url` (see [OpenAI-compatible endpoints](#openai-compatible-endpoints)).
A human-readable label. Defaults to the integration's display name (`OpenAI`) when omitted.
Set this credential as the default OpenAI credential for the organization. Only one credential per integration can be the default.
Optional ISO-8601 datetime after which ModuleX treats the credential as expired.
**Response** — `201 Created` (secret masked):
The credential's UUID. Pass this as `credential_id` to pin a specific OpenAI key on a run.
`openai`.
`llm_provider`.
`api_key`.
Whether this is the organization's default OpenAI credential.
ISO-8601 timestamp of the last resolution, or `null` if never used.
```bash cURL
curl -X POST https://api.modulex.dev/credentials \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "openai",
"display_name": "Production OpenAI key",
"make_default": true,
"auth_data": { "api_key": "sk-proj-abc123" }
}'
```
```python Python
from modulex import Modulex
async with Modulex(
api_key="mx_live_xxx",
organization_id="11111111-1111-1111-1111-111111111111",
) as client:
credential = await client.credentials.create(
"openai",
display_name="Production OpenAI key",
make_default=True,
auth_data={"api_key": "sk-proj-abc123"},
)
print(credential.credential_id)
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_xxx",
organizationId: "11111111-1111-1111-1111-111111111111",
});
const credential = await client.credentials.create({
integrationName: "openai",
displayName: "Production OpenAI key",
makeDefault: true,
authData: { api_key: "sk-proj-abc123" },
});
console.log(credential.credential_id);
```
### Validate a key before saving
`POST /credentials/test-temporary` validates auth data **before** you persist it. ModuleX runs OpenAI's configured test endpoint (`POST https://api.openai.com/v1/chat/completions`, model `gpt-5.4-mini`, `max_tokens: 10`) and treats HTTP `200` with `id`, `choices`, and `model` present as success.
`openai`.
`api_key`.
`{"api_key": "sk-proj-…"}`. Optionally include `base_url`.
The response reports `is_valid`, a human-readable `message`, `tested_at`, and a `test_method` of `api_call`.
```bash cURL
curl -X POST https://api.modulex.dev/credentials/test-temporary \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "openai",
"auth_type": "api_key",
"auth_data": { "api_key": "sk-proj-abc123" }
}'
```
```python Python
result = await client.credentials.test_temporary(
"openai",
"api_key",
{"api_key": "sk-proj-abc123"},
)
print(result.is_valid, result.message)
```
```javascript JavaScript
const result = await client.credentials.testTemporary({
integrationName: "openai",
authType: "api_key",
authData: { api_key: "sk-proj-abc123" },
});
console.log(result.isValid, result.message);
```
### OpenAI-compatible endpoints
OpenAI's auth schema includes an optional `base_url` field, so you can point the same credential at any OpenAI-compatible API (a proxy, gateway, or self-hosted server that speaks the OpenAI wire protocol).
The API base URL. Only change this for an OpenAI-compatible endpoint. ModuleX validates it against `^https?://.*`.
Include `base_url` inside `auth_data` when you create the credential. Leave it unset to use OpenAI directly.
```bash cURL
curl -X POST https://api.modulex.dev/credentials \
-H "Authorization: Bearer mx_live_xxx" \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "openai",
"display_name": "OpenAI-compatible gateway",
"auth_data": {
"api_key": "sk-proxy-abc123",
"base_url": "https://gateway.example.com/v1"
}
}'
```
The catalog model ids on this page (for example `gpt-5.5`) map to OpenAI's own model names via each model's `body_extra.model`. A custom `base_url` must serve those same model names, or the upstream call returns a model-not-found error from your endpoint.
## Available models
ModuleX serves OpenAI's models from its integration catalog. The list below is the catalog as shipped in the backend OpenAI manifest; OpenAI updates models over time, so always treat the **live catalog** ([browse it via the API](#browse-openai-in-the-catalog)) as authoritative.
Each model carries a standardized `id` (the value you pass as `model_id`), pricing in **USD per 1M tokens** (input and output), a context window (`max_input_tokens`), an output cap (`max_output_tokens`), a knowledge cutoff (`data_freshness`), `intelligence` and `speed` scores (1–5), and vision support. Pricing shown is **OpenAI's list price** that ModuleX records for analytics — your actual charge comes from OpenAI, not ModuleX.
### Chat and reasoning models
| `model_id` | Display name | Context (in) | Max output | Input $/1M | Output $/1M | Vision | Cutoff |
| --- | --- | --: | --: | --: | --: | :-: | --- |
| `gpt-5.5` | GPT 5.5 | 1,050,000 | 128,000 | $5.00 | $30.00 | Yes | 2025-12-01 |
| `gpt-5.5-pro` | GPT 5.5 Pro | 1,050,000 | 128,000 | $30.00 | $180.00 | Yes | 2025-12-01 |
| `gpt-5.4` | GPT 5.4 | 1,050,000 | 128,000 | $2.50 | $15.00 | Yes | 2025-08-31 |
| `gpt-5.4-pro` | GPT 5.4 Pro | 1,050,000 | 128,000 | $30.00 | $180.00 | Yes | 2025-08-31 |
| `gpt-5.4-mini` | GPT 5.4 mini | 400,000 | 128,000 | $0.75 | $4.50 | Yes | 2024-05-31 |
| `gpt-5.4-nano` | GPT 5 nano | 400,000 | 128,000 | $0.20 | $1.25 | Yes | 2024-08-31 |
| `gpt-5-chat-latest` | GPT 5 chat latest | 128,000 | 16,384 | $1.25 | $10.00 | Yes | 2024-09-30 |
| `gpt-5.3-codex` | GPT 5.3 codex | 400,000 | 128,000 | $1.75 | $14.00 | Yes | 2025-08-31 |
| `o3-pro` | o3-pro | 200,000 | 100,000 | $20.00 | $80.00 | Yes | 2024-06-01 |
| `o3` | o3 | 200,000 | 100,000 | $2.00 | $8.00 | Yes | 2024-06-01 |
### Embedding models
Embedding models return a vector instead of text (`max_output_tokens` is `0`). Use them to build a [knowledge base](/concepts/knowledge-rag) with OpenAI embeddings, or in a workflow that needs vectors.
| `model_id` | Display name | Dimensions | Max input | Input $/1M | Output $/1M |
| --- | --- | --: | --: | --: | --: |
| `text-embedding-3-large` | Text Embedding 3 Large | 3072 | 8,191 | $0.13 | $0.00 |
| `text-embedding-3-small` | Text Embedding 3 Small | 1536 | 8,191 | $0.02 | $0.00 |
`text-embedding-3-small` produces 1536-dimensional vectors, which match ModuleX's managed vector storage column width. `text-embedding-3-large` produces 3072-dimensional vectors. Pick the embedding model that matches your vector store's dimension when you configure a knowledge base. See [Managed knowledge](/platform/knowledge/managed) and [Knowledge & RAG](/concepts/knowledge-rag).
Every entry in the OpenAI `models[]` array carries these fields. ModuleX stores them verbatim and returns them on the [detail endpoint](#browse-openai-in-the-catalog).
The standardized catalog model id you pass as `model_id` (for example `gpt-5.5`).
The human-readable model name.
The display vendor — `OpenAI`.
The routing provider slug — `openai`. Pass this as `provider_id` in an `llm` config.
The context-window size in tokens.
The maximum tokens the model can return. `0` for embedding models.
The provider request-body fragment, including the real OpenAI wire `model` name. For OpenAI the catalog `id` and `body_extra.model` are the same.
Extra request headers. Empty (`{}`) for every OpenAI model.
A usage blurb describing the model's strengths.
The knowledge cutoff date (ISO date). There is no separate `knowledge_cutoff` field.
A quality score, `1`–`5`.
A latency score, `1`–`5` (higher is faster).
Whether the model accepts image input.
OpenAI's list input price per 1M tokens (flat field, not a nested `pricing` object).
OpenAI's list output price per 1M tokens. `0` for embedding models.
Present and `true` only on embedding models.
The output vector dimension — present only on embedding models (`3072` for large, `1536` for small).
## Select an OpenAI model
Across the API and SDKs, you choose a model with an `llm` configuration object. For OpenAI, every field uses the `openai` slug:
`openai`.
`openai`.
A catalog model id from [Available models](#available-models), for example `gpt-5.5`.
The id of the OpenAI credential to use. Omit it to let ModuleX [resolve a credential](/concepts/credentials-oauth#credential-resolution-at-run-time): your `is_default` OpenAI credential, then the most-recent valid one. ModuleX prefers your own keys over managed keys — and OpenAI is BYOK-only, so resolution always lands on a key you connected.
This is the same shape the [Assistant](/concepts/assistant) and [AI Composer](/concepts/ai-composer) accept for their `llm` field:
```json llm config
{
"integration_name": "openai",
"provider_id": "openai",
"model_id": "gpt-5.5",
"credential_id": "c0ffee00-1111-2222-3333-444455556666"
}
```
In the [LLM node](/workflow-builder/nodes/llm) (and the [Agent node](/workflow-builder/nodes/agent)), set the node's `llm_config` to an OpenAI model. ModuleX resolves the standardized `model_id` to OpenAI's wire model via the catalog's `body_extra.model`, then calls OpenAI with your resolved credential. See [Workflow engine & nodes](/concepts/workflow-engine).
Pass the `llm` object when you start an Assistant chat. The Assistant rebuilds the model from this config on every turn and on resume, so the same `llm` object must be supplied each time. See [Models & settings](/assistant/models-and-settings).
The Composer takes the same `llm` object to generate and edit your workflow graph. If you omit it, ModuleX falls back to the organization's configured Composer default model. See [AI Composer in the builder](/workflow-builder/composer).
In the app's [chat](/platform/chat/overview), pick an OpenAI model from the [model selector](/platform/chat/model-selection). The connected OpenAI credential is used automatically.
**Deprecation routing applies only to managed models.** For managed integrations (`modulexai`), a model marked `deprecated` routes to its `replacement_id` automatically, and unknown ids fall back to the integration default. OpenAI is BYOK (a passthrough integration), so its `model_id` is used as-is — an unknown id is sent straight to OpenAI and fails there. None of the OpenAI catalog models are currently marked deprecated.
## Browse OpenAI in the catalog
The [integration catalog](/integrations/catalog) is the read-only discovery surface. Use it to fetch OpenAI's live models, pricing, and auth schema. These catalog endpoints authenticate with a **Clerk JWT** (the app token), not an `mx_live_*` API key, and still require `X-Organization-ID` and the owner/admin role.
`openai`.
**Response** — `200 OK`, an `IntegrationDetail`:
`openai`.
`OpenAI`.
`llm_provider`.
The OpenAI model list described in [Available models](#available-models).
The OpenAI auth schemas. OpenAI ships a single `api_key` schema with `setup_instructions`, the `api_key` and `base_url` `setup_environment_variables`, and a `test_endpoint`.
`https://platform.openai.com/docs`.
The integration's `extra_metadata` (`status`, `recommended`, timestamps, popularity score).
```bash cURL
curl https://api.modulex.dev/integrations/llm-providers/openai \
-H "Authorization: Bearer " \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111"
```
```bash cURL — list all LLM providers
curl https://api.modulex.dev/integrations/llm-providers \
-H "Authorization: Bearer " \
-H "X-Organization-ID: 11111111-1111-1111-1111-111111111111"
```
```json
{
"name": "openai",
"display_name": "OpenAI",
"description": "OpenAI's GPT models for chat, completion, and embeddings",
"logo": "modulex:openai-themed",
"app_url": "https://platform.openai.com",
"docs_url": "https://platform.openai.com/docs",
"categories": ["AI & LLM Providers", "ai", "chat", "completion"],
"integration_type": "llm_provider",
"version": "1.0.0",
"auth_schemas": [
{
"auth_type": "api_key",
"display_name": "API Key Authentication",
"description": "Connect using OpenAI API Key",
"setup_environment_variables": [
{ "name": "api_key", "required": true, "sensitive": true },
{ "name": "base_url", "required": false, "default": "https://api.openai.com/v1" }
],
"test_endpoint": { "url": "https://api.openai.com/v1/chat/completions", "method": "POST" }
}
],
"models": [
{
"id": "gpt-5.5",
"display_name": "GPT 5.5",
"provider": "OpenAI",
"provider_id": "openai",
"max_input_tokens": 1050000,
"max_output_tokens": 128000,
"supports_vision": true,
"input_usd_per_1m_tokens": 5.0,
"output_usd_per_1m_tokens": 30.0
}
],
"metadata": { "status": "active", "recommended": true, "popularity_score": 92 }
}
```
ModuleX maintains a backend-only `llm_max_tokens` resolver that caps output tokens per scenario (for example chat vs workflow node). Those values are **never returned by any catalog API response** — do not rely on the catalog `max_output_tokens` as the effective per-scenario output cap.
## BYOK billing
OpenAI is **bring-your-own-key**. Usage on your OpenAI credential is billed by OpenAI to your OpenAI account and is **not** metered in ModuleX [credits](/concepts/credits-billing).
BYOK calls — OpenAI included — carry no ModuleX credit gate. There is no markup, and these calls do not draw down your plan allowance or [wallet](/billing/wallet).
Because there is no credit gate on BYOK calls, OpenAI usage does not produce the `402`/`403`/`429` `DenialEnvelope` that managed usage can. See [Usage gating & limits](/billing/usage-gating).
Token costs accrue on your OpenAI account at OpenAI's rates. Set spend limits and monitor usage in the OpenAI dashboard.
ModuleX records token counts and the catalog list price for OpenAI usage for **analytics**, so you can see consumption per workflow or run — but no credits are deducted.
**Want credit-metered, no-key-required models instead?** Use [ModuleX-managed models](/integrations/llm-providers/modulexai) (the `modulexai` provider), which run on ModuleX-provisioned keys and bill in credits — gated by your plan. There is no managed (pooled-key) path for `openai`; OpenAI is always BYOK. See [Credits & metering](/billing/credits).
Rate limits, quotas, and model availability for BYOK calls are governed by **your OpenAI account**, not by ModuleX. A `429` or quota error from OpenAI surfaces as an upstream error on the run, distinct from ModuleX's own [rate limiting](/api-reference/rate-limiting).
## Managing the credential
Day-to-day operations use the standard [credentials API](/concepts/credentials-oauth#the-credentials-api). For OpenAI specifically:
- **Rotate a key.** Secrets are immutable through `PUT /credentials/{id}` (that route updates only `display_name` and metadata). To rotate, create a new OpenAI credential with the new key and delete the old one — there is no rotate endpoint.
- **Set the default.** `POST /credentials/{id}/set-default` makes one OpenAI credential the organization default, used when no `credential_id` is supplied.
- **Test a saved key.** `POST /credentials/{id}/test` re-runs OpenAI's test endpoint against the stored key.
- **Delete.** `DELETE /credentials/{id}` removes it and returns `204`. Runs that relied on it will fail credential resolution until another valid OpenAI credential exists.
See [Managing credentials](/integrations/managing-credentials) for the app workflow and [Credentials & OAuth2](/concepts/credentials-oauth) for the complete API.
## Where to go next
Compare OpenAI with the other model providers, managed and BYOK.
The credit-metered, no-key-required default provider.
The full credential model, resolution precedence, and credentials API.
Call an OpenAI model from a workflow with prompts, variables, and structured output.
---
# Connect LLM providers
URL: https://docs.modulex.dev/integrations/llm-providers/overview
Connect language-model providers to ModuleX as managed (modulexai, billed in credits) or BYOK (your own key, uncosted), and select models for chat, the Assistant, and workflow nodes.
ModuleX runs every language-model call through an **LLM provider**: a connector that exposes a set of **models** and one or more **auth schemas**. You connect a provider once, then any surface that calls a model — the [Chat model selector](/platform/chat/model-selection), the [Assistant](/assistant/models-and-settings), the [LLM node](/workflow-builder/nodes/llm), the [Agent node](/workflow-builder/nodes/agent), and the [AI Composer](/concepts/ai-composer) — can use its models.
There are two ways to connect a provider, and the difference is who pays and how:
ModuleX provisions the upstream provider keys for you. Usage is metered in **credits** against your plan allowance and wallet. No provider account or key required.
You supply your own provider API key. Usage is **billed directly by the provider** with no ModuleX markup, and is **not** charged in ModuleX credits (analytics-only).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4050 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** Diagram of the two connection paths for an LLM provider.
**[IMAGE_DETAILS]:** Show a single "LLM provider" box fanning into two lanes — "ModuleX-managed (modulexai, modulex_key auth)" routed through ModuleX-provisioned keys and metered in credits, and "BYOK (api_key auth)" routed directly to the upstream vendor and billed by the vendor. Label which lane consumes credits. 16:9, light and dark variants, ModuleX brand palette, no UI chrome.
## Supported providers
The catalog ships these LLM providers. The **wire name** is the value you send as `integration_name` when you create a credential or pick a model.
| Provider | Wire name | Connect with | Billing | Page |
| --- | --- | --- | --- | --- |
| ModuleX-managed | `modulexai` | `modulex_key` (no key needed) | Credits | [ModuleX-managed models](/integrations/llm-providers/modulexai) |
| OpenAI | `openai` | `api_key` (BYOK) | Provider-direct | [OpenAI](/integrations/llm-providers/openai) |
| Anthropic | `anthropic` | `api_key` (BYOK) | Provider-direct | [Anthropic](/integrations/llm-providers/anthropic) |
| Google Gemini | `gemini` | `api_key` (BYOK) | Provider-direct | [Google Gemini](/integrations/llm-providers/gemini) |
| xAI Grok | `xai` | `api_key` (BYOK) | Provider-direct | [xAI Grok](/integrations/llm-providers/xai) |
Two further providers exist on the wire but are routing layers, not separately documented destinations. `openrouter` is a BYOK aggregator used internally to route many of the managed models, and `bedrock` carries only deprecated model ids that route to their replacements. Connect `modulexai` for managed access or a first-party provider above for BYOK; you do not need to connect `openrouter` or `bedrock` directly. See [Selecting a model](#selecting-a-model) for how deprecated ids are handled, and the [open questions](#open-questions-tbd) below.
Each provider's detail record is read-only metadata served by the catalog API (`GET /integrations/llm-providers/{provider_name}`). It carries the provider's `models[]` and its `auth_schemas[]`; it never returns or stores your secret key.
## Managed vs BYOK
The two modes differ in authentication, billing, and what you have to supply.
- **Wire name:** `modulexai`.
- **Auth schema:** `modulex_key`. ModuleX provides the upstream key automatically — `setup_environment_variables` is empty, so there is nothing for you to enter.
- **Billing:** **credited.** Every managed turn is metered (see [Credit cost](#credit-cost-for-managed-usage)) and flows through the billing admission gate, which can return a [`DenialEnvelope`](/api-reference/errors) on `402` / `403` / `429` when your allowance and wallet are exhausted.
- **Use it when** you want one provider with no key management, curated models, and unified usage tracking. It is the default and recommended provider.
- Models are curated and may be routed across upstreams (for example, several `modulexai` models route through OpenRouter with a Bedrock-then-Anthropic fallback order). You select by ModuleX `model_id`; the routing is handled for you.
- **Wire names:** `openai`, `anthropic`, `gemini`, `xai`.
- **Auth schema:** `api_key`. You supply the provider's key (and optionally a custom `base_url` for compatible endpoints).
- **Billing:** **uncosted in ModuleX credits.** The upstream provider bills your account directly, with no ModuleX markup. ModuleX records BYOK calls for analytics only; the credit gate does not charge them.
- **Use it when** you have provider accounts, want vendor-direct pricing, or need a specific model not offered under `modulexai`.
- There is no `feature.byok` plan entitlement — BYOK is not plan-gated. You still need the [owner or admin role](/security/roles-permissions) to manage the provider credential.
Managed (`modulexai`) usage **consumes credits and is subject to the billing gate**; BYOK usage is **not** credited. Switching a chat, Assistant, or node from a `modulexai` model to a BYOK model moves that cost off your ModuleX credits and onto your provider bill, and vice versa. Confirm which model is selected before you rely on either billing path.
## Connecting a provider
Managed access needs no setup — `modulexai` is available out of the box and requires no credential. For BYOK, you create a **credential** that stores your provider key (encrypted at rest), in the app or over the API.
### In the app
Open the integration catalog, find the provider (for example, OpenAI), and choose to connect it. You must be an **owner or admin** of the organization.
Paste the provider API key into the field defined by the provider's `api_key` auth schema. Some providers also accept an optional **Base URL** for compatible endpoints.
ModuleX validates the key against the provider's `test_endpoint` before saving (a minimal, low-cost request). On success the credential is stored and becomes selectable wherever models are chosen.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4051 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The connect-credential dialog for a BYOK LLM provider.
**[SCREENSHOT_DETAILS]:** Capture the OpenAI provider connect modal showing the API Key field (masked), the optional Base URL field, and the validate/save action. Use a placeholder key value, never a real secret. Light theme, cropped to the dialog.
### Over the API
Create the credential with `POST /credentials`. The request body is read raw and the **auth type is auto-detected from the body** — sending `auth_data.api_key` creates an `api_key` credential. Authenticate every request per [Authentication](/api-reference/authentication): `Authorization: Bearer mx_live_…` plus `X-Organization-ID`.
The provider wire name — `openai`, `anthropic`, `gemini`, or `xai`. Use `modulexai` only for managed access, which needs no key.
The secret payload. For a BYOK provider, include `api_key`. The presence of `auth_data.api_key` is what selects the `api_key` credential type.
Your provider API key (for example, a key starting `sk-ant-` for Anthropic or `sk-` for OpenAI). Stored encrypted; never returned in responses.
Optional custom base URL for a provider-compatible endpoint. Defaults to the provider's standard API host when omitted.
A human-readable label for the credential, shown in the app and credential list.
When `true`, this credential becomes the default for the integration; any prior default for the same integration is unset.
```bash cURL
curl -X POST https://api.modulex.dev/credentials \
-H "Authorization: Bearer mx_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Organization-ID: 8f1c2b3a-4d5e-6f70-8192-a3b4c5d6e7f8" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "openai",
"display_name": "Production OpenAI key",
"make_default": true,
"auth_data": { "api_key": "sk-proj-xxxxxxxxxxxxxxxxxxxx" }
}'
```
```python Python
import os
from modulex import Modulex
client = Modulex(
api_key=os.environ["MODULEX_API_KEY"], # mx_live_...
organization_id=os.environ["MODULEX_ORG_ID"],
)
credential = await client.credentials.create(
integration_name="openai",
display_name="Production OpenAI key",
make_default=True,
auth_data={"api_key": os.environ["OPENAI_API_KEY"]},
)
print(credential.id)
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: process.env.MODULEX_API_KEY, // mx_live_...
organizationId: process.env.MODULEX_ORG_ID,
});
const credential = await client.credentials.create({
integration_name: "openai",
display_name: "Production OpenAI key",
make_default: true,
auth_data: { api_key: process.env.OPENAI_API_KEY },
});
console.log(credential.id);
```
The SDK method names and shapes above follow the documented credential surface. Confirm the exact SDK method path against the [SDK ⇄ API parity matrix](/sdks/parity); where an SDK lacks a method, call `POST /credentials` directly with cURL.
A successful create returns `201` with the credential record. To check a key before saving it, use `POST /credentials/test-temporary` with `integration_name`, `auth_type: "api_key"`, and `auth_data`; it runs the provider's validation endpoint and returns `is_valid`. For rotation, scoping, and listing, see [Managing credentials](/integrations/managing-credentials).
#### Errors
| Status | Shape | When |
| --- | --- | --- |
| `400` | `{detail}` | `auth_data`/`auth_type` could not be resolved to a known credential type, or validation failed. |
| `401` | `{detail}` | Missing or invalid `Authorization`, or missing `X-Organization-ID`. |
| `403` | `{detail}` | You are not an owner or admin of the organization. |
| `500` | `{detail}` | Unexpected server error while creating the credential. |
The credential routes return the FastAPI `{detail}` `HTTPException` envelope (a string message). The flat `DenialEnvelope` billing shape (`{code, layer, key, current, limit, reason}`) appears only on **managed-usage** surfaces — the run, Composer, Assistant, and managed-knowledge calls that actually meter credits — not on credential CRUD. See [Errors & status codes](/api-reference/errors) for all three envelope shapes.
## Selecting a model
A provider exposes its models in a `models[]` array. You select a model by its ModuleX `model_id` (for example, `claude-sonnet-4.6`), and ModuleX resolves that to the upstream wire model and request shape for you.
### The model record
Each entry in `models[]` carries the fields below. Values come from the provider's catalog record; pricing fields apply to BYOK provider-direct billing and inform managed credit metering.
The ModuleX `model_id` you select (for example, `claude-opus-4.7`, `gpt-5.5`, `gemini-2.5-pro`).
Human-readable model name shown in selectors.
Display vendor, for example `Anthropic` or `OpenAI`.
Routing provider slug — `anthropic`, `openai`, `gemini`, `xai`, or `openrouter` for models routed through the aggregator under `modulexai`.
Maximum context window in tokens.
Maximum tokens the model can generate. `0` for embedding models.
Knowledge-cutoff date (for example, `2026-01-01`). This field, not a `knowledge_cutoff` key, carries the cutoff.
Quality score, 1–5.
Latency score, 1–5 (higher is faster).
Whether the model accepts image input.
Input price per 1M tokens, as a flat number (not a nested `pricing` object).
Output price per 1M tokens.
Present on some models — whether the model supports tool/function calling.
Present on some models — whether JSON-schema structured output is supported.
`true` for embedding models. Embedding models report `embedding_dimension` and a zero output price.
Vector dimension for embedding models (for example, `3072` for `text-embedding-3-large`).
Lifecycle state. Present and set to `deprecated` on retired model ids.
On a deprecated model, the successor `model_id` that ModuleX routes the call to instead.
```json
{
"id": "claude-opus-4.7",
"display_name": "Claude Opus 4.7",
"provider": "Anthropic",
"provider_id": "anthropic",
"max_input_tokens": 1000000,
"max_output_tokens": 128000,
"data_freshness": "2026-01-01",
"intelligence": 5,
"speed": 1,
"supports_vision": true,
"input_usd_per_1m_tokens": 5.0,
"output_usd_per_1m_tokens": 25.0
}
```
### Where you select a model
- **Chat** — pick the model in the chat composer. See [Model selection](/platform/chat/model-selection).
- **Assistant** — set the model in Assistant settings. See [Models & settings](/assistant/models-and-settings).
- **LLM node** — set `model_id` on the node. See [LLM node](/workflow-builder/nodes/llm).
- **Agent node** — set `model_id` on the node. See [Agent node](/workflow-builder/nodes/agent).
### Deprecated models route automatically
When you select a model whose `status` is `deprecated` (or `maintenance`), ModuleX resolves it to its `replacement_id` before the call — for example, a `bedrock-claude-sonnet-4.6` id routes to `claude-sonnet-4.6`. Routing is cycle- and depth-guarded, so a chain of replacements terminates at a live model. You do not need to update saved selections immediately, but prefer the live id for clarity.
## Credit cost for managed usage
BYOK calls are **not** credited. Managed (`modulexai`) calls are metered two ways and charged against your [credits](/billing/credits):
- **Per-turn run charge** — each logical run or chat turn is charged a flat `RUN_CREDIT` of **1** credit.
- **Token metering** — the model's tokens are converted to credits:
```text Token-to-credit formula
cost = (prompt_tokens · input_rate / 1e6 + completion_tokens · output_rate / 1e6) · MARGIN · SCALE
```
where `input_rate`/`output_rate` are the model's `input_usd_per_1m_tokens` / `output_usd_per_1m_tokens`, `MARGIN` is `1.05` (a 5% system margin), and `SCALE` is `100` (so **100 credits = $1.00**, and 1 credit = $0.01). Embedding calls force `completion_tokens = 0`. An unknown model meters to `0`, never a silent fallback rate.
When managed usage exhausts your plan allowance and wallet, the call is denied with a [`DenialEnvelope`](/api-reference/errors) on `402` / `403` / `429`. See [Credits & metering](/billing/credits) and [Usage gating & limits](/billing/usage-gating) for the full model.
## Permissions and access
Connecting, listing, and managing LLM-provider credentials requires the **owner** or **admin** role in the organization (`member` is retired). Every request also needs the org context header `X-Organization-ID`; a missing header is rejected. See [Roles & permissions](/security/roles-permissions) and [Org context & X-Organization-ID](/security/org-context).
## Per-provider pages
The default managed provider (`modulexai`), billed in credits — no key required.
Connect your OpenAI account (BYOK) and use GPT models.
Connect your Anthropic account (BYOK) and use Claude models.
Connect your Google account (BYOK) and use Gemini models.
Connect your xAI account (BYOK) and use Grok models.
## Related
- [Authentication & credentials](/integrations/authentication) — the auth-schema variants and OAuth2 flow for integrations.
- [Managing credentials](/integrations/managing-credentials) — create, rotate, scope, and test credentials.
- [Knowledge providers](/integrations/knowledge-providers/overview) — the vector-store side of managed vs BYOK.
- [Credits & metering](/billing/credits) — what consumes credits and how it is measured.
## Open questions (TBD)
- **OpenRouter and Bedrock pages.** Both names exist on the wire (`openrouter` as the BYOK aggregator behind several managed models; `bedrock` carrying only deprecated, replacement-routed ids), but neither has a canonical documentation page in the current information architecture. Whether to document them as standalone connectable providers is **TBD** pending a product decision.
- **Public catalog base URL.** The provider catalog and credential examples use `https://api.modulex.dev` per the repo-wide convention; the exact public host for these endpoints is not pinned from source and should be confirmed against the deployed environment.
---
# xAI Grok models
URL: https://docs.modulex.dev/integrations/llm-providers/xai
Connect xAI to ModuleX with your own API key, see the available Grok models, and understand how BYOK usage is billed.
xAI is a [BYOK (bring-your-own-key)](/reference/glossary) LLM provider in ModuleX. You connect your own xAI API key, then use Grok models in the [LLM node](/workflow-builder/nodes/llm), the [Agent node](/workflow-builder/nodes/agent), [chat](/platform/chat/model-selection), and the [Assistant](/assistant/models-and-settings). Because xAI is BYOK, xAI bills you directly for token usage and ModuleX adds no credit charge on top — see [BYOK billing](#byok-billing) below.
For the full list of provider types and how managed versus BYOK selection works, see [LLM providers](/integrations/llm-providers/overview). If you would rather have ModuleX provision and meter the model for you in credits, use [ModuleX-managed models](/integrations/llm-providers/modulexai) instead.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4090 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The xAI connection card in the ModuleX integrations/credentials UI.
**[SCREENSHOT_DETAILS]:** Capture the API Key Authentication form for xAI in the credential-management UI: the `API Key` field (masked, sample `xai-…`), the optional `Base URL` field defaulted to `https://api.x.ai/v1`, and the "Test connection" / "Save" controls. Light theme, 16:9, crop to the card.
## What you need
Create a key in the [xAI Console](https://console.x.ai/team) under **API Keys → Create new API key**. xAI keys start with `xai-` (for example `xai-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`). ModuleX validates the key against the pattern `^xai-[a-zA-Z0-9\-_]{20,}$` before saving it.
Credentials are scoped to an [organization](/concepts/organizations-roles). Connecting and managing integrations requires the **owner** or **admin** role — the `member` role is retired. See [roles & permissions](/security/roles-permissions).
To connect xAI over the API or an SDK, you need a ModuleX API key (`mx_live_…`) and your organization id. See [authentication](/api-reference/authentication).
## Connect xAI
You connect xAI by storing your xAI API key as a [credential](/integrations/managing-credentials) for the `xai` integration. You can do this in the app or programmatically.
### In the app
1. Open the [integrations catalog](/integrations/catalog) and select **xAI**, or open **Settings → Credentials**.
2. Choose **API Key Authentication** and paste your xAI key.
3. Optionally set a custom **Base URL** (defaults to `https://api.x.ai/v1`) — only needed for xAI-compatible gateways.
4. Save. ModuleX validates the key with a minimal request before storing it (see [Test a key before saving](#test-a-key-before-saving)).
xAI exposes a single authentication scheme — `api_key`. Its fields are:
Your xAI API key. Stored encrypted and never returned in plaintext. Pattern `^xai-[a-zA-Z0-9\-_]{20,}$`; sample format `xai-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`.
Optional custom API base URL, only needed when pointing at an xAI-compatible API. Must match `^https?://.*`.
### Over the API or an SDK
Create the credential with `POST /credentials`. ModuleX detects the credential type from the body: an `auth_data.api_key` value is stored as an `api_key` credential. Set `make_default: true` to make this the default xAI credential for the organization.
Every request authenticates with `Authorization: Bearer mx_live_…` plus the `X-Organization-ID` header (see [authentication](/api-reference/authentication)).
```bash cURL
curl -X POST https://api.modulex.dev/credentials \
-H "Authorization: Bearer mx_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Organization-ID: 6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "xai",
"display_name": "xAI production key",
"make_default": true,
"auth_data": { "api_key": "xai-..." }
}'
```
```python Python
import asyncio
from modulex import Modulex
async def main():
async with Modulex(
api_key="mx_live_xxxxxxxxxxxxxxxxxxxxxxxx", # or MODULEX_API_KEY
organization_id="6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
) as client:
cred = await client.credentials.create(
integration_name="xai",
display_name="xAI production key",
make_default=True,
auth_data={"api_key": "xai-..."},
)
print(cred.id)
asyncio.run(main())
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_xxxxxxxxxxxxxxxxxxxxxxxx", // or process.env.MODULEX_API_KEY
organizationId: "6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
});
const cred = await client.credentials.create({
integration_name: "xai",
display_name: "xAI production key",
make_default: true,
auth_data: { api_key: "xai-..." },
});
console.log(cred.id);
```
The new credential's identifier. A `201` response returns the credential metadata; the secret is never echoed back.
Creating, listing, and managing credentials and the integration catalog requires the **owner** or **admin** role in the organization. A caller without that role receives a `403`. The integration-catalog read routes (for example `GET /integrations/llm-providers/xai`) are also owner/admin-gated.
### Test a key before saving
Use `POST /credentials/test-temporary` to validate an xAI key without storing it. ModuleX runs the provider's test call — a 10-token `POST` to `https://api.x.ai/v1/chat/completions` against `grok-4-fast` — and reports success when the response status is `200` and includes the fields `id`, `choices`, and `model`.
```bash cURL
curl -X POST https://api.modulex.dev/credentials/test-temporary \
-H "Authorization: Bearer mx_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Organization-ID: 6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "xai",
"auth_type": "api_key",
"auth_data": { "api_key": "xai-..." }
}'
```
```python Python
result = await client.credentials.test_temporary(
integration_name="xai",
auth_type="api_key",
auth_data={"api_key": "xai-..."},
)
print(result.is_valid, result.status_code)
```
```javascript JavaScript
const result = await client.credentials.testTemporary({
integration_name: "xai",
auth_type: "api_key",
auth_data: { api_key: "xai-..." },
});
console.log(result.is_valid, result.status_code);
```
`true` when the test call succeeds.
The HTTP status returned by xAI's test endpoint (`200` on success).
How the credential was validated. For xAI this is `api_call`.
The cost class of the test call. For xAI this is `minimal` (a 10-token request).
## Available models
ModuleX serves Grok models from the catalog at `GET /integrations/llm-providers/xai`. The catalog is read-only metadata used by the credential UI and the builder — it is not the execution path. The models below are the ones ModuleX currently advertises for xAI.
| Model id | Display name | Max input tokens | Max output tokens | Vision | Input $/1M | Output $/1M |
| --- | --- | --- | --- | --- | --- | --- |
| `grok-4-0709` | Grok 4 | 256,000 | 256,000 | Yes | `$3.00` | `$15.00` |
| `grok-code-fast-1` | Grok Code Fast | 256,000 | 10,000 | No | `$0.20` | `$1.50` |
| `grok-4-fast` | Grok 4 Fast | 2,000,000 | 30,000 | Yes | `$0.20` | `$0.50` |
Prices in the table are **xAI's per-token rates** as recorded in the ModuleX catalog, in USD per 1,000,000 tokens. Because xAI is BYOK, these are the rates xAI charges you directly — they are not ModuleX credits. See [BYOK billing](#byok-billing).
Each model id is the catalog id you select in the app and in node configuration. ModuleX maps the catalog id to the underlying xAI wire model and request settings:
`grok-4-0709` — the catalog id you select.
`Grok 4`
`xAI`
`xai` — the routing provider slug.
`256000`
`256000`
`true`
`5` (quality score, 1–5).
`3` (latency score, 1–5; higher is faster).
`2024-10-01` (knowledge cutoff).
`3.0`
`15.0`
ModuleX sends the wire model `grok-4-0709`.
`grok-code-fast-1`
`Grok Code Fast`
`xAI`
`xai`
`256000`
`10000`
`false`
`4`
`3`
`2024-10-01`
`0.2`
`1.5`
Wire model `grok-code-fast-1`. This is a coding-focused model and does not accept image input.
`grok-4-fast`
`Grok 4 Fast`
`xAI`
`xai`
`2000000`
`30000`
`true`
`3`
`4`
`2024-10-01`
`0.2`
`0.5`
Wire model `grok-4-fast`. This is the model ModuleX uses for the connection test.
The model list is served from the ModuleX catalog and may change as xAI releases or deprecates models. Always read `GET /integrations/llm-providers/xai` for the current set rather than hard-coding ids. Catalog reads are cached for up to 10 minutes.
### Read the model catalog
```bash cURL
curl https://api.modulex.dev/integrations/llm-providers/xai \
-H "Authorization: Bearer mx_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Organization-ID: 6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f"
```
```python Python
detail = await client.integrations.llm_provider_detail("xai")
for model in detail.models:
print(model["id"], model["display_name"])
```
```javascript JavaScript
const detail = await client.integrations.llmProvider("xai");
for (const model of detail.models) {
console.log(model.id, model.display_name);
}
```
The response is an integration-detail object whose `models` array contains the entries shown above, plus an `auth_schemas` array describing the `api_key` scheme. A truncated example:
```json Catalog detail (truncated)
{
"name": "xai",
"display_name": "xAI",
"description": "xAI's Grok models for advanced reasoning, coding, and real-time information access",
"integration_type": "llm_provider",
"version": "1.0.0",
"categories": ["AI & LLM Providers", "ai", "chat", "reasoning", "coding"],
"auth_schemas": [
{
"auth_type": "api_key",
"display_name": "API Key Authentication",
"description": "Connect using xAI API Key"
}
],
"models": [
{
"id": "grok-4-0709",
"display_name": "Grok 4",
"max_input_tokens": 256000,
"max_output_tokens": 256000,
"supports_vision": true,
"input_usd_per_1m_tokens": 3.0,
"output_usd_per_1m_tokens": 15.0
}
]
}
```
## Use Grok in ModuleX
Once xAI is connected, select a Grok model id wherever a model can be chosen:
Call Grok with prompts, variables, and structured output inside a workflow.
Run an autonomous step where Grok can call tools and loop.
Pick Grok as the model for a chat conversation.
Configure the Assistant to reason and act with a Grok model.
If your organization holds more than one xAI credential, ModuleX uses the credential marked default for the `xai` integration. Set a different default with `POST /credentials/{credential_id}/set-default`. See [managing credentials](/integrations/managing-credentials).
## BYOK billing
xAI is **bring-your-own-key**, which changes how usage is billed compared with [ModuleX-managed models](/integrations/llm-providers/modulexai).
Token usage is billed by **xAI** against your own API key. ModuleX adds **no credit charge and no markup** for the model call itself. BYOK usage is recorded for analytics only — it does not consume ModuleX [credits](/billing/credits).
ModuleX provisions the model and bills it in **credits** through the [usage gate](/billing/usage-gating), applying a system margin. Use this when you do not want to manage a provider account.
What this means in practice:
- **No ModuleX credit cost for tokens.** A Grok call made with your xAI key is not metered in credits. xAI invoices you directly at its own rates (the per-million-token prices in the [model table](#available-models)).
- **Other ModuleX usage still applies.** Running a workflow or a turn through the Assistant can still consume the flat per-run credit and may pass through the billing gate even when the model itself is BYOK. See [credits & metering](/billing/credits) and [usage gating & limits](/billing/usage-gating).
- **Rate limits and quotas are xAI's.** Token-rate limits, monthly spend caps, and model availability for a BYOK key are governed by your xAI account, not by ModuleX.
BYOK is available on all plans — there is no separate ModuleX entitlement that gates connecting your own xAI key. The pricing matrix on the marketing site lists BYOK for every tier; the only ModuleX-side billing that applies to a BYOK call is the non-model usage described above. **TBD:** confirm with the billing owner that no per-call ModuleX surcharge applies to BYOK model calls before treating "no markup" as a guarantee.
## Errors
Catalog and credential operations return ModuleX's standard error shapes. See [errors & status codes](/api-reference/errors) for the full taxonomy.
| Status | When it happens | Shape |
| --- | --- | --- |
| `400` | Invalid `auth_data`/`auth_type` on credential create, or asking a typed endpoint for the wrong integration type (for example `xai` is not a tool). | `{detail: string}` |
| `401` | Missing or invalid `Authorization` / missing `X-Organization-ID`. | `{detail: string}` |
| `403` | Caller is not an owner/admin in the organization. | `{detail: string}` |
| `404` | Unknown provider, for example `GET /integrations/llm-providers/` returns `LLM provider not found`. | `{detail: string}` |
| `422` | Query/parameter validation error. | `{detail: [ ... ]}` |
| `500` | Unhandled server error. | `{detail: string}` |
A bad xAI key does not surface as a ModuleX `401`. Connection validation happens against xAI: `POST /credentials/test-temporary` (or saving with validation) returns `is_valid: false` with the status xAI returned (for example `401` from `api.x.ai`). The ModuleX request itself still succeeds.
## Related
All providers, and how managed vs BYOK selection works.
The credit-billed managed alternative to BYOK.
How integrations authenticate and the auth schema variants.
Create, default, rotate, and scope credentials.
---
# Managing credentials
URL: https://docs.modulex.dev/integrations/managing-credentials
Create, connect, test, rotate, and revoke ModuleX integration credentials in the app and via the API. Credentials are organization-scoped, encrypted at rest, and require an owner or admin role.
A **credential** is a stored, encrypted auth record that links your organization to an integration (a tool, an LLM provider, or a knowledge provider). Each credential has a `credential_id`, an `auth_type`, an owning organization, and an optional `display_name`. This page covers the full lifecycle: create and connect, inspect and test, set a default, rotate, and revoke — both in the app and via the API.
For the auth-type variants themselves (API key, OAuth2 with PKCE, bearer, and the other schemas) and the OAuth2 connect flow in depth, see [Authentication & credentials](/integrations/authentication) and [Credentials & OAuth2](/concepts/credentials-oauth). For request lifecycle and base URLs, see the [API overview](/api-reference/overview).
Credentials are **organization-scoped**. The organization is always taken from the `X-Organization-ID` header (and the authenticated caller's active org) — never from the request body. A credential created under one organization is invisible to every other organization. See [Org context & X-Organization-ID](/security/org-context).
## Who can manage credentials
Every credential endpoint requires an **owner** or **admin** role on the organization (the backend dependency is `organization_admin_required`). The `member` role is retired and is not a current first-class role. See [Roles & permissions](/security/roles-permissions).
| Outcome | HTTP status | When |
| --- | --- | --- |
| Missing `X-Organization-ID` | `400` | No org context on the request |
| Not a member of the org | `403` | Caller is not in the organization |
| Member but not owner/admin | `403` | Role check fails |
| Inactive user | `403` | The user account is not active |
| Rate limited | `429` | The org-class `api` rate limit (fail-open), with `X-RateLimit-*` and `Retry-After` headers |
The credential CRUD and OAuth endpoints have **no per-call credit gate** — they return the standard `{"detail": ...}` error envelope, not the flat `DenialEnvelope`. The credit gate runs later, at execution time, only for ModuleX-managed (`modulex_key`) credentials. There is no `402` on these routes. For the gated surfaces and the `DenialEnvelope` shape, see [Errors & status codes](/api-reference/errors) and [Usage gating & limits](/billing/usage-gating).
## Authenticate every request
All examples use the same auth as the rest of the API: an `Authorization: Bearer` token (a `mx_live_*` API key, or a Clerk JWT from the app) plus the `X-Organization-ID` header. The SDKs send both for you once configured. See [Authentication](/api-reference/authentication).
```bash cURL
curl -s https://api.modulex.dev/credentials \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: 9a1f0c7e-2b44-4f1a-9c3d-7e5b2a1d8f60"
```
```python Python
from modulex import Modulex
# Reads MODULEX_API_KEY / MODULEX_ORGANIZATION_ID from the environment,
# or pass them explicitly:
async with Modulex(
api_key="mx_live_your_api_key",
organization_id="9a1f0c7e-2b44-4f1a-9c3d-7e5b2a1d8f60",
) as client:
grouped = await client.credentials.list()
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex({
apiKey: "mx_live_your_api_key",
organizationId: "9a1f0c7e-2b44-4f1a-9c3d-7e5b2a1d8f60",
});
const grouped = await client.credentials.list();
```
## Create and connect a credential
### In the app
1. Open **Settings → Credentials** (or **Browse** to start from the integration catalog), then choose the integration you want to connect.
2. Pick the auth type the integration supports — `oauth2`, `api_key`, `bearer_token`, `modulex_key`, or a `custom` schema with fields from the integration's manifest.
3. For API key, bearer, and custom types, fill in the secret fields and select **Test** to validate before saving (see [Test a credential](#test-a-credential)). For OAuth2 you are redirected to the provider's consent screen, then back to ModuleX.
4. Optionally set a **display name** and toggle **Make default** so this credential is used automatically for the integration.
5. Save. The secret is encrypted at rest and only a masked form is ever shown again.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4030 · [APP_VIDEO]**
**[APP_VIDEO_DESCRIPTION]:** Connecting an integration credential from Settings → Credentials, including the test-before-save step and the OAuth2 redirect.
**[APP_VIDEO_DETAILS]:** Record in the live app: open Settings → Credentials, pick an API-key integration (e.g. Tavily), enter a key, run Test (show the success toast), set a display name, toggle Make default, save. Then show an OAuth2 integration (e.g. GitHub) redirecting to consent and returning with a created credential. 30-45s, light mode, 16:9, highlight the Test and Make default controls.
### Via the API
`POST /credentials` creates a credential. The body is read raw and the credential **type is auto-detected** from `auth_data` / `auth_type` / `integration_name` — you do not send a `type` field. Returns `201 Created` with a `CredentialResponse`.
The integration to attach the credential to (for example `slack`, `openai`, `github`). Must be a live integration. For an external MCP server, prefer the dedicated MCP create path described in [Authentication & credentials](/integrations/authentication).
The secret payload, encrypted at rest. The presence of specific keys selects the credential type:
- `auth_data.api_key` present → `api_key` credential.
- `auth_data.token` or `auth_data.bearer_token` present → `bearer_token` credential.
- `auth_data.access_token` present **and** a top-level `oauth_config` present → `oauth2` credential.
- For `auth_type: "custom"`, `auth_data` holds the custom fields declared by the integration's manifest (must be non-empty).
- If none of the above match, the request fails with `400` (`Invalid auth_data or auth_type ...`).
Explicit auth type. Required for `modulex_key` (ModuleX-managed pooled key — send no `auth_data`) and `custom`. For `api_key`, `bearer_token`, and `oauth2`, the type is inferred from `auth_data` and you may omit it. Accepted values: `oauth2`, `api_key`, `bearer_token`, `modulex_key`, `custom`. (The backend also tolerates a legacy `bearer`.)
OAuth2 client configuration (`client_id`, `client_secret`, `token_url`, and related fields) sent **only** when creating an `oauth2` credential directly with an `access_token`. Most OAuth2 credentials are created by the connect flow on the [Authentication & credentials](/integrations/authentication) page rather than this field.
A human-friendly label, for example `Production Slack`. Defaults to a generated name.
Optional free-form metadata stored alongside the credential.
When `true`, this credential becomes the default for its integration, unsetting any prior default.
Optional ISO-8601 expiry timestamp (`SDK only` — accepted by the SDK create methods).
```bash cURL
curl -X POST https://api.modulex.dev/credentials \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: 9a1f0c7e-2b44-4f1a-9c3d-7e5b2a1d8f60" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "slack",
"display_name": "Production Slack",
"make_default": true,
"auth_data": { "api_key": "xoxb-your-slack-token" }
}'
```
```python Python
from modulex import Modulex
async with Modulex() as client:
credential = await client.credentials.create(
"slack",
auth_data={"api_key": "xoxb-your-slack-token"},
display_name="Production Slack",
make_default=True,
)
print(credential.credential_id)
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex();
const credential = await client.credentials.create({
integration_name: "slack",
auth_data: { api_key: "xoxb-your-slack-token" },
display_name: "Production Slack",
make_default: true,
});
console.log(credential.credential_id);
```
The unique identifier for the credential. Use it for every subsequent operation.
The integration this credential belongs to.
One of `tool`, `llm_provider`, `knowledge_provider`.
The credential's label.
The detected auth type: `oauth2`, `api_key`, `bearer_token`, `modulex_key`, or `custom`.
Whether this credential is the default for its integration.
ISO-8601 creation timestamp.
ISO-8601 last-update timestamp.
ISO-8601 timestamp of last use, or `null` if never used.
ISO-8601 expiry, or `null` if the credential does not expire.
**Errors:** `400` validation (`CredentialValidationError` / `CredentialServiceError`, including invalid `auth_data`), `401` / `403` auth, `429` rate limit, `500` on unexpected failure.
## List and inspect credentials
### List
`GET /credentials` returns credentials grouped by integration. Supplying `integration_name` switches to a flat list for that one integration.
Filter to a single integration and return a flat list instead of the grouped shape.
Filter by auth type (`oauth2`, `api_key`, `bearer_token`, `modulex_key`, `custom`).
Page size. Range `1`–`500`.
Number of items to skip. Minimum `0`.
```bash cURL
curl -s "https://api.modulex.dev/credentials?auth_type=oauth2&limit=50" \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: 9a1f0c7e-2b44-4f1a-9c3d-7e5b2a1d8f60"
```
```python Python
from modulex import Modulex
async with Modulex() as client:
# Grouped by integration
grouped = await client.credentials.list()
# Flat list for one integration
slack_creds = await client.credentials.list(integration_name="slack")
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex();
// Grouped by integration
const grouped = await client.credentials.list();
// Flat list for one integration
const slackCreds = await client.credentials.list({ integrationName: "slack" });
```
The grouped response keys each integration by name; each group lists its credentials with the per-credential fields above plus the integration `logo`, `total_count`, and the set of `auth_types` present:
```json Grouped response
{
"integrations": {
"github": {
"integration_name": "github",
"integration_type": "tool",
"logo": "https://.../github.svg",
"credentials": [
{
"credential_id": "b3f1c2d4-aa11-4e55-8c90-12ab34cd56ef",
"integration_name": "github",
"integration_type": "tool",
"display_name": "Production GitHub",
"auth_type": "oauth2",
"is_default": true,
"created_at": "2026-01-19T12:00:00",
"updated_at": "2026-01-19T12:00:00",
"last_used_at": null,
"expires_at": "2026-02-19T12:00:00",
"credentials_metadata": null
}
],
"total_count": 1,
"auth_types": ["oauth2"]
}
},
"total_credentials": 1,
"total_integrations": 1,
"filters": { "auth_type": null }
}
```
Response fields are **snake_case** on the wire (for example `credentials_metadata`, `auth_type`, `display_name`). The SDKs convert to their own conventions (`integrationName` in JS, snake_case in Python).
### Get one credential
`GET /credentials/{credential_id}` returns one credential with masked secrets. Pass `include_masked=true` to also receive a per-field map of masked values. The secret itself is never returned — only labels and masked fragments (for example `xoxb***-end`).
When `true`, add a dict of per-field masked auth values to the response.
```bash cURL
curl -s "https://api.modulex.dev/credentials/b3f1c2d4-aa11-4e55-8c90-12ab34cd56ef" \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: 9a1f0c7e-2b44-4f1a-9c3d-7e5b2a1d8f60"
```
```python Python
from modulex import Modulex
async with Modulex() as client:
detail = await client.credentials.get(
"b3f1c2d4-aa11-4e55-8c90-12ab34cd56ef",
include_masked=True,
)
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex();
const detail = await client.credentials.get(
"b3f1c2d4-aa11-4e55-8c90-12ab34cd56ef",
{ includeMasked: true },
);
```
The detail response adds `organization_id`, `created_by`, `created_by_email`, and `auth_data_masked` (a label for OAuth2/managed keys, or a masked secret for API-key and bearer credentials).
**Errors:** `404` not found, `403` access denied, `400` service error.
## Test a credential
ModuleX can validate a credential against the integration's declared test endpoint.
- `POST /credentials/test-temporary` validates an unsaved credential **before** you store it (used by the test-before-save step in the app). Body: `integration_name`, `auth_type` (`api_key` / `bearer_token` / `oauth2`), `auth_data`.
- `POST /credentials/{credential_id}/test` validates a credential you have already saved. A credential past its `expires_at` returns `is_valid: false` with `Credential has expired`.
If the integration declares no test endpoint, the test returns `is_valid: true` with a `test_method` of `none` or `basic` and a "no test endpoint" message.
```bash cURL
# Validate before saving
curl -X POST https://api.modulex.dev/credentials/test-temporary \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: 9a1f0c7e-2b44-4f1a-9c3d-7e5b2a1d8f60" \
-H "Content-Type: application/json" \
-d '{
"integration_name": "tavily",
"auth_type": "api_key",
"auth_data": { "api_key": "tvly-your-key" }
}'
# Test an existing credential
curl -X POST "https://api.modulex.dev/credentials/b3f1c2d4-aa11-4e55-8c90-12ab34cd56ef/test" \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: 9a1f0c7e-2b44-4f1a-9c3d-7e5b2a1d8f60"
```
```python Python
from modulex import Modulex
async with Modulex() as client:
# Validate before saving
temp = await client.credentials.test_temporary(
integration_name="tavily",
auth_type="api_key",
auth_data={"api_key": "tvly-your-key"},
)
# Test an existing credential
result = await client.credentials.test("b3f1c2d4-aa11-4e55-8c90-12ab34cd56ef")
print(result.is_valid)
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex();
// Validate before saving
const temp = await client.credentials.testTemporary({
integration_name: "tavily",
auth_type: "api_key",
auth_data: { api_key: "tvly-your-key" },
});
// Test an existing credential
const result = await client.credentials.test("b3f1c2d4-aa11-4e55-8c90-12ab34cd56ef");
console.log(result.is_valid);
```
```json test-temporary response
{
"is_valid": true,
"message": "Credential is valid for tavily (test cost: minimal)",
"tested_at": "2026-01-19T12:00:00",
"test_method": "api_call",
"integration_name": "tavily",
"auth_type": "api_key",
"test_endpoint": "https://api.tavily.com/search",
"status_code": 200,
"cost_level": "minimal"
}
```
Whether the credential passed validation.
Human-readable result detail.
How validation ran: `api_call`, `basic`, or `none`.
ISO-8601 timestamp of the test.
**Errors:** `test-temporary` wraps any failure as `500` (`Failed to test credential: ...`). The saved-credential `test` returns `404` / `403` for missing or forbidden credentials.
## Set a default credential
When an integration has more than one credential, ModuleX resolves which one to use in this precedence order: an explicitly requested `credential_id`, then the credential marked default, then the most recent valid **user** credential, then the most recent valid **ModuleX-managed** (`modulex_key`) credential. `POST /credentials/{credential_id}/set-default` marks a credential as the default and unsets any prior default for the same integration.
```bash cURL
curl -X POST "https://api.modulex.dev/credentials/b3f1c2d4-aa11-4e55-8c90-12ab34cd56ef/set-default" \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: 9a1f0c7e-2b44-4f1a-9c3d-7e5b2a1d8f60"
```
```python Python
from modulex import Modulex
async with Modulex() as client:
updated = await client.credentials.set_default(
"b3f1c2d4-aa11-4e55-8c90-12ab34cd56ef",
)
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex();
const updated = await client.credentials.setDefault(
"b3f1c2d4-aa11-4e55-8c90-12ab34cd56ef",
);
```
You can also update a credential's label or metadata in place with `PUT /credentials/{credential_id}` (body: `display_name?`, `metadata?` — secrets are not updatable here; to change a secret, rotate).
## Rotate a credential
There is **no dedicated rotate endpoint**. Rotation in ModuleX is a deliberate three-step pattern: create the replacement, promote it to default, then revoke the old one. This keeps the integration usable throughout — the new credential is in place and default before the old secret is removed.
1. **Create** a new credential for the same integration with the new secret (`POST /credentials`).
2. **Promote** it with `make_default: true` on create, or `POST /credentials/{new_id}/set-default` afterward, so resolution prefers it immediately.
3. **Revoke** the old credential with `DELETE /credentials/{old_id}` once the new one is verified.
```bash cURL
# 1. Create the replacement as the new default
NEW_ID=$(curl -s -X POST https://api.modulex.dev/credentials \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: 9a1f0c7e-2b44-4f1a-9c3d-7e5b2a1d8f60" \
-H "Content-Type: application/json" \
-d '{"integration_name":"slack","display_name":"Production Slack (rotated)","make_default":true,"auth_data":{"api_key":"xoxb-new-token"}}' \
| python3 -c "import sys,json;print(json.load(sys.stdin)['credential_id'])")
# 2. (Optional) verify the new credential
curl -X POST "https://api.modulex.dev/credentials/$NEW_ID/test" \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: 9a1f0c7e-2b44-4f1a-9c3d-7e5b2a1d8f60"
# 3. Revoke the old credential
curl -X DELETE "https://api.modulex.dev/credentials/OLD_CREDENTIAL_ID" \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: 9a1f0c7e-2b44-4f1a-9c3d-7e5b2a1d8f60"
```
```python Python
from modulex import Modulex
async with Modulex() as client:
# 1. Create the replacement as the new default
new = await client.credentials.create(
"slack",
auth_data={"api_key": "xoxb-new-token"},
display_name="Production Slack (rotated)",
make_default=True,
)
# 2. Verify it
check = await client.credentials.test(new.credential_id)
# 3. Revoke the old credential once verified
if check.is_valid:
await client.credentials.delete("OLD_CREDENTIAL_ID")
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex();
// 1. Create the replacement as the new default
const fresh = await client.credentials.create({
integration_name: "slack",
auth_data: { api_key: "xoxb-new-token" },
display_name: "Production Slack (rotated)",
make_default: true,
});
// 2. Verify it
const check = await client.credentials.test(fresh.credential_id);
// 3. Revoke the old credential once verified
if (check.is_valid) {
await client.credentials.delete("OLD_CREDENTIAL_ID");
}
```
The manual OAuth2 token-refresh endpoint (`POST /credentials/{credential_id}/oauth2/refresh`) and the app's `refreshOAuth2` action are **known to be broken** and must not be relied on to rotate or refresh OAuth2 credentials. To refresh an expired OAuth2 connection, **reconnect** the integration through the OAuth connect flow (which creates a fresh credential), then revoke the stale one. ModuleX also refreshes OAuth2 tokens automatically at execution time when a token is within 5 minutes of expiry, so most refresh happens without any manual step. See [Known limitations](/reference/known-limitations).
## Revoke a credential
Revoking deletes the credential permanently. `DELETE /credentials/{credential_id}` returns `204 No Content`; in the app, open the credential's detail panel and choose **Delete**.
```bash cURL
curl -X DELETE "https://api.modulex.dev/credentials/b3f1c2d4-aa11-4e55-8c90-12ab34cd56ef" \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: 9a1f0c7e-2b44-4f1a-9c3d-7e5b2a1d8f60"
```
```python Python
from modulex import Modulex
async with Modulex() as client:
await client.credentials.delete("b3f1c2d4-aa11-4e55-8c90-12ab34cd56ef")
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex();
await client.credentials.delete("b3f1c2d4-aa11-4e55-8c90-12ab34cd56ef");
```
Deletion is **permanent** — there is no soft-delete or undo. If the deleted credential was the default for its integration, any node or agent that relied on default resolution will fall through to the next valid credential, or fail with no credential found if none remains. Rotate (create the replacement first) instead of deleting in place for production integrations.
**Errors:** `404` not found, `403` access denied, `400` service error.
## Per-organization scope and isolation
Every credential belongs to exactly one organization, and the active organization is fixed by the `X-Organization-ID` header on each request — it is never read from the body. The practical consequences:
- **No cross-org access.** A credential created in one organization cannot be listed, fetched, tested, or used from another. Switching organizations changes the credential set entirely.
- **Encryption is org-scoped.** Each credential's secret is encrypted with a key derived from the organization ID and the credential ID, so ciphertext cannot be reused across credentials or organizations. See [Data security & encryption](/security/data-encryption).
- **Owner/admin only.** Because credentials are organization-wide, only owners and admins can create, change, or revoke them. See [Roles & permissions](/security/roles-permissions).
- **Resolution stays in-org.** When a tool or LLM node runs, ModuleX resolves the credential within the same organization using the precedence in [Set a default credential](#set-a-default-credential).
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4031 · [IMAGE]**
**[IMAGE_DESCRIPTION]:** Diagram showing two organizations, each with its own isolated set of integration credentials, with the `X-Organization-ID` header selecting the active org's credential scope.
**[IMAGE_DETAILS]:** Two side-by-side org boxes (Org A, Org B), each containing distinct credential records for the same integrations (e.g. Slack, GitHub). An incoming API request labeled `X-Organization-ID: Org A` routes only to Org A's credentials; a dashed line to Org B is crossed out. Note "encrypted per (org, credential)". Clean, light mode, 16:9.
## Auditing credential changes
`GET /credentials/{credential_id}/audit` returns the change history for a credential from the unified audit log. Logged operations include `CREDENTIAL_CREATED`, `CREDENTIAL_UPDATED`, `CREDENTIAL_DELETED`, `CREDENTIAL_ROTATED`, `CREDENTIAL_REVOKED`, `CREDENTIAL_ACTIVATED`, `CREDENTIAL_DEACTIVATED`, and `MCP_DISCOVERY_REFRESHED`.
Page size. Range `1`–`500`.
Number of items to skip. Minimum `0`.
```bash cURL
curl -s "https://api.modulex.dev/credentials/b3f1c2d4-aa11-4e55-8c90-12ab34cd56ef/audit?limit=50" \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: 9a1f0c7e-2b44-4f1a-9c3d-7e5b2a1d8f60"
```
```python Python
from modulex import Modulex
async with Modulex() as client:
logs = await client.credentials.audit(
"b3f1c2d4-aa11-4e55-8c90-12ab34cd56ef",
limit=50,
)
```
```javascript JavaScript
import { Modulex } from "modulex-js";
const client = new Modulex();
const logs = await client.credentials.audit(
"b3f1c2d4-aa11-4e55-8c90-12ab34cd56ef",
{ limit: 50 },
);
```
A usage-statistics endpoint (`GET /credentials/{credential_id}/usage`) and the audit response are documented in the API reference, but both have **known field-shape issues** today — treat their exact response fields as `TBD` until verified against a live response. See [Known limitations](/reference/known-limitations).
## Errors
Credential endpoints return the standard `{"detail": }` envelope (the dict form only for the rate-limit `429`). There is no `DenialEnvelope` and no `402` on these routes.
| Status | Meaning |
| --- | --- |
| `200` | Read, update, set-default, or test succeeded |
| `201` | Credential created |
| `204` | Credential deleted (revoked) |
| `400` | Missing `X-Organization-ID`, invalid `auth_data` / `auth_type`, or service validation error |
| `401` | Missing or invalid auth token |
| `403` | Not a member, or not owner/admin |
| `404` | Credential not found in this organization |
| `429` | Org-class API rate limit (fail-open); see `X-RateLimit-*` and `Retry-After` headers |
| `500` | Unexpected error (and the `test-temporary` failure wrapper) |
For the full error model across all surfaces — including the three error-envelope shapes and the billing `DenialEnvelope` on gated endpoints — see [Errors & status codes](/api-reference/errors).
## Related pages
Request lifecycle, base URLs, and how every operation is shown three ways.
The auth-type variants and the OAuth2 (PKCE) connect flow.
How ModuleX stores and resolves credentials, conceptually.
Which actions require an owner or admin role.
---
# Integrations: connect your tools to ModuleX
URL: https://docs.modulex.dev/integrations/overview
Connect ModuleX to 175 services and call their tools from your workflows and the Assistant. Learn what integrations are, browse the catalog, and connect credentials with OAuth or your own keys.
An integration is how ModuleX talks to a service you already use — GitHub, Slack, Gmail, Notion, Salesforce, and many more. Once a service is connected, ModuleX can run its actions for you: open an issue, send a message, read a row, create a contact. You connect the service once, and every workflow and the [Assistant](/assistant/overview) can use it from then on.
**🎬 MEDIA PLACEHOLDER · MX-MEDIA-4000 · [SCREENSHOT]**
**[SCREENSHOT_DESCRIPTION]:** The ModuleX integration catalog: a grid of integration cards with logos, names, and a category filter.
**[SCREENSHOT_DETAILS]:** Capture the integrations catalog page in the ModuleX app. Show a grid of logo cards (for example GitHub, Slack, Gmail, Notion, Salesforce, HubSpot), the search box, and the category filter rail. 16:9, light theme, no personal data visible. Highlight the search and category controls.
## Integrations and tools, in plain terms
Two words come up everywhere in ModuleX. They are easy to keep straight.
A connection to one external service — for example **GitHub** or **Slack**. It bundles the service's logo, its actions, and how to authenticate to it.
One callable action a connected integration exposes — for example "create an issue" or "send a message." A single integration usually offers many tools.
So you connect an **integration** once, and that unlocks all of its **tools**. ModuleX ships **175 integrations** today, and together they expose 600+ tool actions you can call.
ModuleX has **175 integrations** as of this writing. You may see other counts in older material — this is the current, verified figure.
## Where you use integration tools
A connected tool is available in two places, and you do not have to choose up front.
Drop a [tool node](/workflow-builder/nodes/tool) onto the canvas, pick the integration and the action, and the workflow calls it on every run. This is the reusable, repeatable path.
Ask the [Assistant](/assistant/overview) in plain language. It finds the right tool among your connected integrations, calls it for you, and pauses for approval when an action is sensitive.
The catalog is shared. A service you connect for the Assistant is the same connection a workflow uses, and the credentials you store work for both.
## Browse the catalog
The catalog is the home for every integration ModuleX can connect to. You can search by name and filter by category to find what you need.
Browse all 175 integrations by category, see each one's logo and description, and find the tools it offers.
Categories in the catalog are descriptive labels (such as productivity, developer tools, marketing, and CRM), and a single integration can appear under more than one. Use the search box if you already know the service you want.
## Connect a service: credentials and BYOK
Before ModuleX can act on your behalf, you tell it how to authenticate to the service. ModuleX stores that connection as an encrypted **credential** scoped to your [organization](/concepts/organizations-roles), so your whole team can reuse it without re-entering secrets.
There are two ways a service authenticates, depending on what it supports.
For services that support it, you click **Connect**, sign in on the provider's own page, and approve access. ModuleX never sees your password — it receives a scoped token. Many connectors use this flow, with PKCE where the provider supports it.
For services that use API keys, you paste a key (or other fields the service needs) into ModuleX. The same idea applies to model and knowledge providers: connect your own provider account and your usage is billed directly by that provider, with no ModuleX markup.
Under the hood, an integration declares one or more **auth schemas**, and ModuleX shows you the right form for each. There are six schema variants in total — OAuth2, bearer token, API key, a ModuleX-managed key, custom, and internal — but as a user you simply see the connect button or the fields a service asks for.
See the full picture: OAuth flows, API keys, BYOK, and how ModuleX stores and resolves your credentials.
ModuleX-managed model and knowledge usage is metered in [credits](/concepts/credits-billing). BYOK usage is billed by the provider you connected, not by ModuleX. See [credits and the billing model](/concepts/credits-billing) for the details.
## Use a tool in a workflow
Connecting a service and using one of its tools takes a few steps. Here is the path from zero to a running tool call.
Open the [catalog](/integrations/catalog), search for the service you want, and open it to see the tools it offers.
Click **Connect** and either approve the OAuth flow or paste your API key. ModuleX saves the credential to your organization so it is reusable. See [authentication and credentials](/integrations/authentication).
In the [workflow builder](/workflow-builder/overview), add a [tool node](/workflow-builder/nodes/tool), then pick the integration and the specific action you want to run.
Fill in the action's parameters, pulling values from earlier nodes with references such as `{{node_id.field}}` where you need them.
Run the workflow. The tool node calls the service, and its result is written into run state for the next node to use.
Learn how the tool node selects an action, maps parameters, and returns results inside a workflow.
## Call a tool from your own code
You can also list the catalog programmatically — for example to discover which integrations exist before wiring up a run. Every request authenticates with `Authorization: Bearer mx_live_…` plus your `X-Organization-ID` header. See [authentication](/api-reference/authentication).
```bash cURL
curl https://api.modulex.dev/integrations/tools \
-H "Authorization: Bearer mx_live_your_api_key" \
-H "X-Organization-ID: org_your_organization_id"
```
```python Python
import httpx
resp = httpx.get(
"https://api.modulex.dev/integrations/tools",
headers={
"Authorization": "Bearer mx_live_your_api_key",
"X-Organization-ID": "org_your_organization_id",
},
)
for integration in resp.json():
print(integration["name"], "-", integration["display_name"])
```
```javascript JavaScript
const resp = await fetch("https://api.modulex.dev/integrations/tools", {
headers: {
Authorization: "Bearer mx_live_your_api_key",
"X-Organization-ID": "org_your_organization_id",
},
});
const integrations = await resp.json();
for (const integration of integrations) {
console.log(integration.name, "-", integration.display_name);
}
```
The catalog endpoint returns a list of integrations, each with its `name`, `display_name`, `description`, and categories:
```json Response
[
{
"name": "github",
"display_name": "GitHub",
"description": "Manage repositories, issues, and pull requests.",
"logo": "modulex:github",
"categories": ["Developer Tools & Infrastructure"],
"integration_type": "tool",
"version": "1.0.0"
}
]
```
Listing the catalog requires the **owner** or **admin** role in the organization you pass in `X-Organization-ID`. The retired `member` role is not a current role — see [roles and permissions](/security/roles-permissions).
## A note on installing the package
If you are running ModuleX yourself, the integrations ship in a Python package that the runtime loads at startup. Installing it pulls in the core dependencies only.
ModuleX does **not** currently provide working install extras such as `[all]` or per-tool extras like `[github,slack]`. Those groups are not populated yet, so asking for them only emits a pip warning and installs the core package. Install the base package, then add any extra SDKs a specific tool needs by hand. See [installing and using integrations](/integrations/install) for the current, accurate steps.
## Where to go next
Browse all 175 integrations by category and find the tools you need.
Connect a service with OAuth or your own API key, and learn how ModuleX stores credentials.
Call a connected integration's action from inside a workflow.
A step-by-step walkthrough: connect a service and call its tool from a workflow.
---
# AgentMail Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/agentmail
Integrate AgentMail into your workflow. Create and manage email inboxes, send and receive messages, reply to threads, manage drafts, and organize threads with labels.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/agentmail/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **AgentMail** to any ModuleX agent or workflow. API-first email for agents and automation: create inboxes, send and receive messages, reply to and forward threads, manage drafts, and organize conversations with labels — over the AgentMail REST API (`api.agentmail.to`).
**Categories**: Communication · Email · Automation · **Auth**: API Key · **Actions**: 21
## Authentication
### API Key Authentication
Authenticate using your AgentMail API key
Sign up or log in at https://agentmail.to
Open the dashboard and navigate to the API Keys section
Create a new API key or copy your existing one
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| AgentMail API Key | Your AgentMail API key | Yes | `-` |
## Available Actions
### Parameters
ID of the inbox to send from
Recipient email address (comma-separated for multiple)
Email subject line
Plain text email body
HTML email body
CC recipient email addresses (comma-separated)
BCC recipient email addresses (comma-separated)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"thread_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Thread Id"
},
"message_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message Id"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"to": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "To"
}
},
"required": [
"success"
],
"title": "SendMessageOutput",
"type": "object"
}
```
### Parameters
ID of the inbox to reply from
ID of the message to reply to
Plain text reply body
HTML reply body
Override recipient email addresses (comma-separated)
CC email addresses (comma-separated)
BCC email addresses (comma-separated)
Reply to all recipients of the original message (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message Id"
},
"thread_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Thread Id"
}
},
"required": [
"success"
],
"title": "ReplyMessageOutput",
"type": "object"
}
```
### Parameters
ID of the inbox containing the message
ID of the message to forward
Recipient email addresses (comma-separated)
Override subject line
Additional plain text to prepend
Additional HTML to prepend
CC recipient email addresses (comma-separated)
BCC recipient email addresses (comma-separated)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message Id"
},
"thread_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Thread Id"
}
},
"required": [
"success"
],
"title": "ForwardMessageOutput",
"type": "object"
}
```
### Parameters
ID of the inbox to list messages from
Maximum number of results to return
Pagination token for the next page of results
### Response
```json
{
"$defs": {
"MessageSummary": {
"additionalProperties": false,
"description": "A single message row in ``list_messages``.",
"properties": {
"message_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message Id"
},
"from_": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "From"
},
"to": {
"items": {
"type": "string"
},
"title": "To",
"type": "array"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"preview": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Preview"
},
"timestamp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
}
},
"title": "MessageSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"messages": {
"items": {
"$ref": "#/$defs/MessageSummary"
},
"title": "Messages",
"type": "array"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"next_page_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page Token"
}
},
"required": [
"success"
],
"title": "ListMessagesOutput",
"type": "object"
}
```
### Parameters
ID of the inbox containing the message
ID of the message to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message Id"
},
"thread_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Thread Id"
},
"from_": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "From"
},
"to": {
"items": {
"type": "string"
},
"title": "To",
"type": "array"
},
"cc": {
"items": {
"type": "string"
},
"title": "Cc",
"type": "array"
},
"bcc": {
"items": {
"type": "string"
},
"title": "Bcc",
"type": "array"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
},
"html": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Html"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
},
"timestamp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
}
},
"required": [
"success"
],
"title": "GetMessageOutput",
"type": "object"
}
```
### Parameters
ID of the inbox containing the message
ID of the message to update
Comma-separated labels to add to the message
Comma-separated labels to remove from the message
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message Id"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
}
},
"required": [
"success"
],
"title": "UpdateMessageOutput",
"type": "object"
}
```
### Parameters
ID of the inbox to list threads from
Maximum number of results to return
Pagination token for the next page of results
Comma-separated labels to filter threads by
Filter threads before this ISO 8601 timestamp
Filter threads after this ISO 8601 timestamp
### Response
```json
{
"$defs": {
"ThreadSummary": {
"additionalProperties": false,
"description": "A single thread row in ``list_threads``.",
"properties": {
"thread_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Thread Id"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"senders": {
"items": {
"type": "string"
},
"title": "Senders",
"type": "array"
},
"recipients": {
"items": {
"type": "string"
},
"title": "Recipients",
"type": "array"
},
"message_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Message Count"
},
"last_message_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Message At"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"title": "ThreadSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"threads": {
"items": {
"$ref": "#/$defs/ThreadSummary"
},
"title": "Threads",
"type": "array"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"next_page_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page Token"
}
},
"required": [
"success"
],
"title": "ListThreadsOutput",
"type": "object"
}
```
### Parameters
ID of the inbox containing the thread
ID of the thread to retrieve
### Response
```json
{
"$defs": {
"ThreadMessage": {
"additionalProperties": false,
"description": "A single message inside ``get_thread``.",
"properties": {
"message_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message Id"
},
"from_": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "From"
},
"to": {
"items": {
"type": "string"
},
"title": "To",
"type": "array"
},
"cc": {
"items": {
"type": "string"
},
"title": "Cc",
"type": "array"
},
"bcc": {
"items": {
"type": "string"
},
"title": "Bcc",
"type": "array"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
},
"html": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Html"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
},
"timestamp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
}
},
"title": "ThreadMessage",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"thread_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Thread Id"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"senders": {
"items": {
"type": "string"
},
"title": "Senders",
"type": "array"
},
"recipients": {
"items": {
"type": "string"
},
"title": "Recipients",
"type": "array"
},
"message_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Message Count"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
},
"last_message_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Message At"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"messages": {
"items": {
"$ref": "#/$defs/ThreadMessage"
},
"title": "Messages",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetThreadOutput",
"type": "object"
}
```
### Parameters
ID of the inbox containing the thread
ID of the thread to update
Comma-separated labels to add to the thread
Comma-separated labels to remove from the thread
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"thread_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Thread Id"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
}
},
"required": [
"success"
],
"title": "UpdateThreadOutput",
"type": "object"
}
```
### Parameters
ID of the inbox containing the thread
ID of the thread to delete
Force permanent deletion instead of moving to trash (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"deleted": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted"
}
},
"required": [
"success"
],
"title": "DeleteThreadOutput",
"type": "object"
}
```
### Parameters
ID of the inbox to create the draft in
Recipient email addresses (comma-separated)
Draft subject line
Plain text draft body
HTML draft body
CC recipient email addresses (comma-separated)
BCC recipient email addresses (comma-separated)
ID of message being replied to
ISO 8601 timestamp to schedule sending
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"draft_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Draft Id"
},
"inbox_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Inbox Id"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"to": {
"items": {
"type": "string"
},
"title": "To",
"type": "array"
},
"cc": {
"items": {
"type": "string"
},
"title": "Cc",
"type": "array"
},
"bcc": {
"items": {
"type": "string"
},
"title": "Bcc",
"type": "array"
},
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
},
"html": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Html"
},
"preview": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Preview"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
},
"in_reply_to": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "In Reply To"
},
"send_status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Send Status"
},
"send_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Send At"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"required": [
"success"
],
"title": "CreateDraftOutput",
"type": "object"
}
```
### Parameters
ID of the inbox to list drafts from
Maximum number of results to return
Pagination token for the next page of results
### Response
```json
{
"$defs": {
"DraftSummary": {
"additionalProperties": false,
"description": "A single draft row in ``list_drafts``.",
"properties": {
"draft_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Draft Id"
},
"inbox_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Inbox Id"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"to": {
"items": {
"type": "string"
},
"title": "To",
"type": "array"
},
"cc": {
"items": {
"type": "string"
},
"title": "Cc",
"type": "array"
},
"bcc": {
"items": {
"type": "string"
},
"title": "Bcc",
"type": "array"
},
"preview": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Preview"
},
"send_status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Send Status"
},
"send_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Send At"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"title": "DraftSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"drafts": {
"items": {
"$ref": "#/$defs/DraftSummary"
},
"title": "Drafts",
"type": "array"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"next_page_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page Token"
}
},
"required": [
"success"
],
"title": "ListDraftsOutput",
"type": "object"
}
```
### Parameters
ID of the inbox the draft belongs to
ID of the draft to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"draft_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Draft Id"
},
"inbox_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Inbox Id"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"to": {
"items": {
"type": "string"
},
"title": "To",
"type": "array"
},
"cc": {
"items": {
"type": "string"
},
"title": "Cc",
"type": "array"
},
"bcc": {
"items": {
"type": "string"
},
"title": "Bcc",
"type": "array"
},
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
},
"html": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Html"
},
"preview": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Preview"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
},
"in_reply_to": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "In Reply To"
},
"send_status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Send Status"
},
"send_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Send At"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"required": [
"success"
],
"title": "GetDraftOutput",
"type": "object"
}
```
### Parameters
ID of the inbox containing the draft
ID of the draft to update
Recipient email addresses (comma-separated)
Draft subject line
Plain text draft body
HTML draft body
CC recipient email addresses (comma-separated)
BCC recipient email addresses (comma-separated)
ISO 8601 timestamp to schedule sending
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"draft_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Draft Id"
},
"inbox_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Inbox Id"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"to": {
"items": {
"type": "string"
},
"title": "To",
"type": "array"
},
"cc": {
"items": {
"type": "string"
},
"title": "Cc",
"type": "array"
},
"bcc": {
"items": {
"type": "string"
},
"title": "Bcc",
"type": "array"
},
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
},
"html": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Html"
},
"preview": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Preview"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
},
"in_reply_to": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "In Reply To"
},
"send_status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Send Status"
},
"send_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Send At"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"required": [
"success"
],
"title": "UpdateDraftOutput",
"type": "object"
}
```
### Parameters
ID of the inbox containing the draft
ID of the draft to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"deleted": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted"
}
},
"required": [
"success"
],
"title": "DeleteDraftOutput",
"type": "object"
}
```
### Parameters
ID of the inbox containing the draft
ID of the draft to send
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message Id"
},
"thread_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Thread Id"
}
},
"required": [
"success"
],
"title": "SendDraftOutput",
"type": "object"
}
```
### Parameters
Username for the inbox email address
Domain for the inbox email address
Display name for the inbox
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"inbox_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Inbox Id"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"required": [
"success"
],
"title": "CreateInboxOutput",
"type": "object"
}
```
### Parameters
Maximum number of results to return
Pagination token for the next page of results
### Response
```json
{
"$defs": {
"InboxSummary": {
"additionalProperties": false,
"description": "A single inbox row in ``list_inboxes``.",
"properties": {
"inbox_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Inbox Id"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"title": "InboxSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"inboxes": {
"items": {
"$ref": "#/$defs/InboxSummary"
},
"title": "Inboxes",
"type": "array"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"next_page_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page Token"
}
},
"required": [
"success"
],
"title": "ListInboxesOutput",
"type": "object"
}
```
### Parameters
ID of the inbox to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"inbox_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Inbox Id"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"required": [
"success"
],
"title": "GetInboxOutput",
"type": "object"
}
```
### Parameters
ID of the inbox to update
New display name for the inbox
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"inbox_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Inbox Id"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"required": [
"success"
],
"title": "UpdateInboxOutput",
"type": "object"
}
```
### Parameters
ID of the inbox to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"deleted": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted"
}
},
"required": [
"success"
],
"title": "DeleteInboxOutput",
"type": "object"
}
```
## Limits & Quotas
- All calls go to `https://api.agentmail.to/v0` over HTTPS with a 30s
client timeout.
- List endpoints are paginated: pass `limit` and the returned
`next_page_token` (via `page_token`) to page through results.
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising. Plan for
retries on the agent side based on the error string.
## Related integrations
## Links
- [AgentMail](https://agentmail.to)
---
# Ahrefs Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/ahrefs
SEO toolset providing backlink analysis, referring domain data, and site explorer metrics via the Ahrefs REST API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/ahrefs/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Ahrefs** to any ModuleX agent or workflow. SEO backlink analysis and referring domain data via the Ahrefs REST API (`api.ahrefs.com/v3`).
**Categories**: Marketing & Advertising · SEO · Marketing · Web Search & Scraping · **Auth**: API Key · **Actions**: 3
## Authentication
### API Key
Authenticate with an Ahrefs API v3 key (Account settings -> API keys; requires an eligible paid plan, key valid 1 year)
Sign in to Ahrefs as a workspace owner or admin
Go to Account settings -> API keys
Create a new API key and copy it (each key is valid for 1 year)
Paste the key into ModuleX
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Ahrefs API Key | Ahrefs API v3 key, sent as Authorization: Bearer <key> | Yes | `-` |
## Available Actions
### Parameters
Domain or URL to get backlinks for
List of columns to return (e.g. url_from, url_to, ahrefs_rank, anchor, page_title)
Mode of operation: exact, domain, subdomains, or prefix (Default: `domain`)
Number of results to return (Default: `1000`)
### Response
```json
{
"$defs": {
"BacklinkItem": {
"additionalProperties": false,
"description": "A single backlink record returned by the Ahrefs API.",
"properties": {
"url_from": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url From"
},
"url_to": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url To"
},
"ahrefs_rank": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Ahrefs Rank"
},
"anchor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Anchor"
},
"page_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Page Title"
},
"first_seen": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Seen"
},
"last_seen": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Seen"
},
"domain_rating": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Domain Rating"
},
"extra": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"description": "Additional fields returned by the API based on the select parameter",
"title": "Extra"
}
},
"title": "BacklinkItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"backlinks": {
"items": {
"$ref": "#/$defs/BacklinkItem"
},
"title": "Backlinks",
"type": "array"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
}
},
"required": [
"success"
],
"title": "GetBacklinksOutput",
"type": "object"
}
```
### Parameters
Domain or URL to get backlinks for
List of columns to return (e.g. url_from, url_to, ahrefs_rank, anchor, page_title)
Mode of operation: exact, domain, subdomains, or prefix (Default: `domain`)
Number of results to return (Default: `1000`)
### Response
```json
{
"$defs": {
"BacklinkItem": {
"additionalProperties": false,
"description": "A single backlink record returned by the Ahrefs API.",
"properties": {
"url_from": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url From"
},
"url_to": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url To"
},
"ahrefs_rank": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Ahrefs Rank"
},
"anchor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Anchor"
},
"page_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Page Title"
},
"first_seen": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Seen"
},
"last_seen": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Seen"
},
"domain_rating": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Domain Rating"
},
"extra": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"description": "Additional fields returned by the API based on the select parameter",
"title": "Extra"
}
},
"title": "BacklinkItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"backlinks": {
"items": {
"$ref": "#/$defs/BacklinkItem"
},
"title": "Backlinks",
"type": "array"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
}
},
"required": [
"success"
],
"title": "GetBacklinksOnePerDomainOutput",
"type": "object"
}
```
### Parameters
Domain or URL to get referring domains for
List of columns to return for referring domains (e.g. domain, domain_rating, backlinks)
Mode of operation: exact, domain, subdomains, or prefix (Default: `domain`)
Number of results to return (Default: `1000`)
### Response
```json
{
"$defs": {
"ReferringDomainItem": {
"additionalProperties": false,
"description": "A single referring domain record returned by the Ahrefs API.",
"properties": {
"domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Domain"
},
"domain_rating": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Domain Rating"
},
"backlinks": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Backlinks"
},
"first_seen": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Seen"
},
"last_seen": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Seen"
},
"extra": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"description": "Additional fields returned by the API based on the select parameter",
"title": "Extra"
}
},
"title": "ReferringDomainItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"refdomains": {
"items": {
"$ref": "#/$defs/ReferringDomainItem"
},
"title": "Refdomains",
"type": "array"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
}
},
"required": [
"success"
],
"title": "GetReferringDomainsOutput",
"type": "object"
}
```
## Limits & Quotas
- Rate limits depend on your Ahrefs subscription plan (Lite, Standard, Advanced, Enterprise).
- API usage is metered against monthly "API rows" quota included in your plan.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Ahrefs](https://ahrefs.com)
---
# Airtable Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/airtable
Cloud-based database platform for organizing, storing, and collaborating on structured data with spreadsheet-like interface and powerful automation capabilities.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/airtable/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Airtable** to any ModuleX agent or workflow. CRUD against the Airtable REST API (`api.airtable.com/v0`): base + table discovery via `/meta/`, record list/get/create/update/delete via `/ /`.
**Categories**: Project & Task Management · Project Management · Workflow · Automation · **Auth**: Personal Access Token · **Actions**: 7
## Authentication
### Personal Access Token
Authenticate using your Airtable Personal Access Token. Create one at airtable.com/create/tokens
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Airtable Personal Access Token | Your Airtable Personal Access Token for API authentication | Yes | `patXXXXXXXXXXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX` |
## Available Actions
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"bases": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Bases",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListBasesOutput",
"type": "object"
}
```
### Parameters
The ID of the Airtable base (starts with 'app')
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"tables": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Tables",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"base_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Base Id"
}
},
"required": [
"success"
],
"title": "ListTablesOutput",
"type": "object"
}
```
### Parameters
The ID of the Airtable base
Name or ID of the table
Maximum number of records to return (1-100) (Default: `100`)
Airtable formula to filter records
Field name to sort by
Sort direction ('asc' or 'desc') (Default: `asc`)
Name or ID of a view to use for filtering/sorting
### Response
```json
{
"$defs": {
"AirtableRecord": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"fields": {
"additionalProperties": true,
"title": "Fields",
"type": "object"
},
"createdTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Createdtime"
}
},
"title": "AirtableRecord",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"records": {
"items": {
"$ref": "#/$defs/AirtableRecord"
},
"title": "Records",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"table": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Table"
},
"base_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Base Id"
}
},
"required": [
"success"
],
"title": "ListRecordsOutput",
"type": "object"
}
```
### Parameters
The ID of the Airtable base
Name or ID of the table
The ID of the record (starts with 'rec')
### Response
```json
{
"$defs": {
"AirtableRecord": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"fields": {
"additionalProperties": true,
"title": "Fields",
"type": "object"
},
"createdTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Createdtime"
}
},
"title": "AirtableRecord",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"record": {
"anyOf": [
{
"$ref": "#/$defs/AirtableRecord"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetRecordOutput",
"type": "object"
}
```
### Parameters
The ID of the Airtable base
Name or ID of the table
List of {field: value} record objects
If true, Airtable converts string values to the appropriate cell types (Default: `false`)
### Response
```json
{
"$defs": {
"AirtableRecord": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"fields": {
"additionalProperties": true,
"title": "Fields",
"type": "object"
},
"createdTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Createdtime"
}
},
"title": "AirtableRecord",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"records": {
"items": {
"$ref": "#/$defs/AirtableRecord"
},
"title": "Records",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"table": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Table"
},
"base_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Base Id"
}
},
"required": [
"success"
],
"title": "CreateRecordsOutput",
"type": "object"
}
```
### Parameters
The ID of the Airtable base
Name or ID of the table
Records to update; each is {'id': 'rec…', 'fields': {…}} or {'id': 'rec…', 'field_a': value, …}
If true, Airtable converts string values to the appropriate cell types (Default: `false`)
### Response
```json
{
"$defs": {
"AirtableRecord": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"fields": {
"additionalProperties": true,
"title": "Fields",
"type": "object"
},
"createdTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Createdtime"
}
},
"title": "AirtableRecord",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"records": {
"items": {
"$ref": "#/$defs/AirtableRecord"
},
"title": "Records",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"table": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Table"
},
"base_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Base Id"
},
"updated_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated Count"
}
},
"required": [
"success"
],
"title": "UpdateRecordsOutput",
"type": "object"
}
```
### Parameters
The ID of the Airtable base
Name or ID of the table
List of record IDs to delete (each starts with 'rec')
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"deleted_ids": {
"items": {
"type": "string"
},
"title": "Deleted Ids",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"table": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Table"
},
"base_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Base Id"
},
"deleted_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted Count"
}
},
"required": [
"success"
],
"title": "DeleteRecordsOutput",
"type": "object"
}
```
## Limits & Quotas
- Airtable caps batch record operations at **10 records per request**;
`create/update/delete_records` split larger inputs automatically.
- `update_records` accepts both shapes per record:
`{"id": "rec…", "fields": {"X": 1}}` (canonical) and
`{"id": "rec…", "X": 1, "Y": 2}` (flat top-level fields). Both
normalize to the canonical wire shape internally.
- `delete_records` uses `?records[]=rec1&records[]=rec2` query
parameters (Airtable's documented batch-delete contract).
- Partial-batch failures surface as `success=False` + the count of
records that completed before the error (via `updated_count` /
`deleted_count`).
## Related integrations
## Links
- [Airtable](https://airtable.com)
---
# Airweave Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/airweave
Search across your synced data sources using Airweave. Supports semantic search with hybrid, neural, or keyword retrieval strategies. Optionally generate AI-powered answers from search results.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/airweave/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Airweave** to any ModuleX agent or workflow. AI-powered semantic search across your synced data collections via the Airweave Search REST API (`api.airweave.ai`). One tool retrieves relevant content from a collection using hybrid, neural, or keyword strategies, and can optionally synthesize an AI-generated answer.
**Categories**: Web Search & Scraping · Vector Search · Knowledge Base · **Auth**: API Key · **Actions**: 1
## Authentication
### API Key Authentication
Authenticate using your Airweave API key
Go to https://app.airweave.ai and sign up or log in
Open the API Keys section of your dashboard
Create a new API key or copy your existing one
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Airweave API Key | Your Airweave API key from app.airweave.ai | Yes | `-` |
## Available Actions
### Parameters
The readable ID of the collection to search
The search query text
Maximum number of results to return
Retrieval strategy: 'hybrid' (default), 'neural', or 'keyword'
Generate query variations to improve recall
Reorder results for improved relevance using an LLM
Generate a natural-language answer to the query
### Response
```json
{
"$defs": {
"SearchResultItem": {
"additionalProperties": false,
"description": "A single result row returned by ``search``.",
"properties": {
"entity_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Entity Id"
},
"source_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Source Name"
},
"md_content": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Md Content"
},
"score": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Score"
},
"metadata": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Metadata"
},
"breadcrumbs": {
"items": {
"type": "string"
},
"title": "Breadcrumbs",
"type": "array"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
}
},
"title": "SearchResultItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"results": {
"items": {
"$ref": "#/$defs/SearchResultItem"
},
"title": "Results",
"type": "array"
},
"completion": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Completion"
},
"total_results": {
"default": 0,
"title": "Total Results",
"type": "integer"
}
},
"required": [
"success"
],
"title": "SearchOutput",
"type": "object"
}
```
## Limits & Quotas
- **Collection-scoped**: every search runs against one collection's
readable ID; results carry per-source attribution (`source_name`,
`breadcrumbs`, `url`).
- **Answer generation**: setting `generate_answer=true` runs an extra
LLM synthesis step and populates the `completion` field; expect higher
latency.
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising. Plan for
retries on the agent side based on the error string.
## Related integrations
## Links
- [Airweave](https://airweave.ai)
---
# Algolia Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/algolia
Search and indexing platform for building fast, relevant search experiences
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/algolia/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Algolia** to any ModuleX agent or workflow. Search and indexing platform for building fast, relevant search experiences via the Algolia REST API (`{application_id}-dsn.algolia.net` for reads, `{application_id}.algolia.net` for writes).
**Categories**: Developer Tools & Infrastructure · Search · **Auth**: Algolia API Credentials · **Actions**: 4
## Authentication
### Algolia API Credentials
Authenticate using your Algolia Application ID and API Key
Go to https://dashboard.algolia.com and sign in
Navigate to Settings > API Keys
Copy your Application ID and Admin API Key
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Application ID | Your Algolia Application ID from the dashboard | Yes | `ABCDEF1234` |
| Admin API Key | Your Algolia Admin API Key (or a key with appropriate permissions) | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
The name of the Algolia index to browse
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"hits": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Hits",
"type": "array"
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cursor"
}
},
"required": [
"success"
],
"title": "BrowseRecordsOutput",
"type": "object"
}
```
### Parameters
The name of the Algolia index
List of object IDs (strings) to delete from the index
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"task_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Task Id"
},
"object_ids": {
"items": {
"type": "string"
},
"title": "Object Ids",
"type": "array"
}
},
"required": [
"success"
],
"title": "DeleteRecordsOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"index_names": {
"items": {
"type": "string"
},
"title": "Index Names",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListIndexNameOptionsOutput",
"type": "object"
}
```
### Parameters
The name of the Algolia index
List of JSON objects to save. Each must have an 'objectID' field.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"task_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Task Id"
},
"object_ids": {
"items": {
"type": "string"
},
"title": "Object Ids",
"type": "array"
}
},
"required": [
"success"
],
"title": "SaveRecordsOutput",
"type": "object"
}
```
## Limits & Quotas
- Rate limits depend on the Algolia plan (Community, Standard, Premium). Community plans have lower indexing and search operation limits.
- Search operations: typically thousands per second on paid plans.
- Indexing operations: batch limits vary by plan (10 MB per batch maximum payload size).
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Algolia](https://www.algolia.com)
---
# Amazon Alexa Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/amazon-alexa
Simulate and test Alexa skills via the Alexa Skills Management API (SMAPI).
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/amazon_alexa/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Amazon Alexa** to any ModuleX agent or workflow. Simulate and test Alexa skills via the Alexa Skills Management API (`api.amazonalexa.com/v2`).
**Categories**: AI & Machine Learning · Voice Assistants · IoT · Smart Home · **Auth**: OAuth2 · **Actions**: 2
## Authentication
### OAuth2 Authentication
Connect using Amazon OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Amazon OAuth App Client ID from the Amazon Developer Console | Yes | `amzn1.application-oa2-client.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
| Client Secret | Amazon OAuth App Client Secret | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://www.amazon.com/ap/oa`
- **Token URL**: `https://api.amazon.com/auth/o2/token`
- **Scopes**: `alexa::ask:skills:readwrite`, `alexa::ask:skills:test`
## Available Actions
### Parameters
The unique identifier for the Alexa skill.
The stage of the skill: development or live.
Utterance text from a user to Alexa.
Locale for the virtual device used in the simulation (e.g. en-US, en-GB, de-DE, fr-FR, ja-JP). (Default: `en-US`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"simulation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Simulation Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
}
},
"required": [
"success"
],
"title": "SimulateSkillOutput",
"type": "object"
}
```
### Parameters
The unique identifier for the Alexa skill.
The stage of the skill: development or live.
The identifier for the simulation.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"simulation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Simulation Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"description": "Simulation result data from the Alexa API",
"title": "Result"
}
},
"required": [
"success"
],
"title": "GetSimulationResultsOutput",
"type": "object"
}
```
## Limits & Quotas
- The Alexa SMAPI is rate-limited per developer account; exact limits are not publicly documented but throttling may occur at high request volumes.
- Simulation requests are asynchronous: `simulate_skill` returns a simulation ID immediately; poll with `get_simulation_results` to retrieve outcomes.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Amazon Alexa](https://developer.amazon.com/alexa)
---
# Amazon Selling Partner Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/amazon-selling-partner
Amazon Selling Partner API for managing orders, inventory, pricing, and reports on Amazon marketplaces
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/amazon_selling_partner/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Amazon Selling Partner** to any ModuleX agent or workflow. Manage orders, inventory, pricing, and reports on Amazon marketplaces via the Amazon Selling Partner API (`sellingpartnerapi-na.amazon.com`).
**Categories**: E-Commerce · Marketplace · Fulfillment · **Auth**: OAuth2 · **Actions**: 8
## Authentication
### OAuth2 Authentication
Connect using Amazon Selling Partner OAuth (Login with Amazon)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Amazon SP-API OAuth App Client ID from your developer application | Yes | `-` |
| Client Secret | Amazon SP-API OAuth App Client Secret | Yes | `-` |
| SP-API Base URL | Selling Partner API regional endpoint. Use https://sellingpartnerapi-na.amazon.com for North America (default), https://sellingpartnerapi-eu.amazon.com for Europe, or https://sellingpartnerapi-fe.amazon.com for the Far East. Pick the endpoint that matches your seller account's region. | Yes | `https://sellingpartnerapi-na.amazon.com` |
#### OAuth Configuration
- **Authorization URL**: `https://www.amazon.com/ap/oa`
- **Token URL**: `https://api.amazon.com/auth/o2/token`
## Available Actions
### Parameters
The Amazon Marketplace ID (e.g. ATVPDKIKX0DER for US)
Set to true to return inventory summaries with additional summarized inventory details and quantities (Default: `false`)
A start date and time in ISO8601 format. If specified, all inventory summaries that have changed since then are returned. Must be no earlier than 18 months prior to the current date.
A list of seller SKUs for which to return inventory summaries (up to 50 SKUs). Elements are strings.
### Response
```json
{
"$defs": {
"InventorySummary": {
"additionalProperties": false,
"properties": {
"asin": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Asin"
},
"fn_sku": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Fn Sku"
},
"seller_sku": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Seller Sku"
},
"condition": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Condition"
},
"total_quantity": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Quantity"
},
"product_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Product Name"
}
},
"title": "InventorySummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"inventory_summaries": {
"items": {
"$ref": "#/$defs/InventorySummary"
},
"title": "Inventory Summaries",
"type": "array"
}
},
"required": [
"success"
],
"title": "CheckFbaInventoryLevelsOutput",
"type": "object"
}
```
### Parameters
The Amazon Marketplace ID
Fetch orders created after this ISO date
Fetch orders created before this ISO date
The email address of a buyer to filter orders
An order identifier specified by the seller. If provided, other filters like FulfillmentChannels, OrderStatuses, PaymentMethod cannot be used.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"orders": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Orders",
"type": "array"
}
},
"required": [
"success"
],
"title": "FetchOrdersByDateRangeOutput",
"type": "object"
}
```
### Parameters
A list of report types used to filter reports. Refer to SP-API Report Type Values documentation. Elements are strings.
The Amazon Marketplace ID to filter reports
A list of processing statuses used to filter reports. Valid values: CANCELLED, DONE, FATAL, IN_PROGRESS, IN_QUEUE. Elements are strings.
The earliest report creation date and time in ISO 8601 format. Default is 90 days ago.
The latest report creation date and time in ISO 8601 format. Default is now.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"reports": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Reports",
"type": "array"
}
},
"required": [
"success"
],
"title": "GenerateSalesInventoryReportsOutput",
"type": "object"
}
```
### Parameters
The Amazon Marketplace ID
The Amazon order ID to fetch details for
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"order": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Order"
}
},
"required": [
"success"
],
"title": "GetOrderDetailsOutput",
"type": "object"
}
```
### Parameters
The Amazon Marketplace ID
Filter inbound shipments by status. Valid values: WORKING, SHIPPED, RECEIVING, CANCELLED, DELETED, CLOSED, ERROR, IN_TRANSIT, DELIVERED, CHECKED_IN. Elements are strings.
A date for selecting inbound shipments that were last updated after (or at) a specified time
A date for selecting inbound shipments that were last updated before (or at) a specified time
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"shipments": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Shipments",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListInboundShipmentsOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"MarketplaceOption": {
"additionalProperties": false,
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Label"
},
"value": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
}
},
"title": "MarketplaceOption",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"marketplaces": {
"items": {
"$ref": "#/$defs/MarketplaceOption"
},
"title": "Marketplaces",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListMarketplaceIdOptionsOutput",
"type": "object"
}
```
### Parameters
The Amazon Marketplace ID
Indicates whether ASIN values or seller SKU values are used to identify items. Valid values: Asin, Sku
A list of ASINs or seller SKUs depending on item_type (up to 20 identifiers). Elements are strings.
Filters the offer listings based on customer type. Valid values: Consumer, Business
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"pricing_data": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Pricing Data",
"type": "array"
}
},
"required": [
"success"
],
"title": "OptimizeProductPricingOutput",
"type": "object"
}
```
### Parameters
The Amazon Marketplace ID
A time interval for selecting order metrics. Two dates separated by two hyphens (first date inclusive; second exclusive) in ISO8601 format. Example: 2018-09-01T00:00:00-07:00--2018-09-04T00:00:00-07:00
The granularity of the grouping of order metrics. Valid values: Hour, Day, Week, Month, Year, Total
An IANA-compatible time zone for determining the day boundary. Required when specifying a granularity value greater than Hour.
Filters results by buyer type. Valid values: All, B2B, B2C
Filters results by fulfillment network. Valid values: MFN (merchant fulfillment), AFN (Amazon fulfillment)
Specifies the day that the week starts on when granularity=Week. Valid values: Monday, Sunday. Default: Monday
Filters results by ASIN. Cannot be specified together with sku.
Filters results by SKU. Cannot be specified together with asin.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"order_metrics": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Order Metrics",
"type": "array"
}
},
"required": [
"success"
],
"title": "RetrieveSalesPerformanceReportsOutput",
"type": "object"
}
```
## Limits & Quotas
- SP-API enforces per-endpoint rate limits varying by selling partner type (standard vs. grantless). Typical burst: 1-30 requests/second depending on the endpoint.
- Orders API: 1 request per second burst, with a restore rate of 1 request per second.
- Inventory API: 2 requests per second burst.
- Pricing API: 10 requests per 1 second burst (for `getCompetitivePrice`).
- Reports API: varies per report type; creation is throttled at a lower rate than retrieval.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Amazon Selling Partner](https://sellercentral.amazon.com)
---
# Amplitude Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/amplitude
Track events, identify users and groups, search for users, query analytics, and retrieve revenue data from Amplitude
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/amplitude/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Amplitude** to any ModuleX agent or workflow. Track events, identify users and groups, search for users, query analytics, and retrieve revenue data from Amplitude via its HTTP V2, Identify, Dashboard REST, and User Profile APIs.
**Categories**: Analytics & Data · Product Analytics · Marketing · **Auth**: Amplitude API Key + Secret Key · **Actions**: 11
## Authentication
### Amplitude API Key + Secret Key
Authenticate with your Amplitude project's API Key (used to send events and identify users) and Secret Key (required for the Dashboard REST API and User Profile analytics endpoints).
Sign in to Amplitude and open the project you want to use.
Go to Settings -> Projects -> (your project) -> General.
Copy the 'API Key' and the 'Secret Key' shown for the project.
Provide the API Key for event tracking; the Secret Key is also needed for analytics/dashboard queries.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| API Key | Amplitude project API Key (used for event tracking and Dashboard Basic auth). | Yes | `-` |
| Secret Key | Amplitude project Secret Key (required for Dashboard REST API and User Profile queries). | No | `-` |
## Available Actions
### Parameters
Name of the event (e.g., "page_view", "purchase").
User ID (required if no device_id).
Device ID (required if no user_id).
Custom event properties as a JSON object.
User properties to set (supports $set, $setOnce, $add, $append, $unset).
Event timestamp in milliseconds since epoch.
Session start time in milliseconds since epoch (-1 for no session).
Unique ID for deduplication (within a 7-day window).
Application version string.
Platform (e.g., "Web", "iOS", "Android").
Two-letter country code.
Language code (e.g., "en").
IP address for geo-location (use "$remote" for request IP).
Price of the item purchased.
Quantity of items purchased.
Revenue amount.
Product identifier.
Revenue type (e.g., "purchase", "refund").
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"code": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Code"
},
"events_ingested": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Events Ingested"
},
"payload_size_bytes": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Payload Size Bytes"
},
"server_upload_time": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Server Upload Time"
}
},
"required": [
"success"
],
"title": "SendEventOutput",
"type": "object"
}
```
### Parameters
User properties to set. Use operations like $set, $setOnce, $add, $append, $unset.
User ID (required if no device_id).
Device ID (required if no user_id).
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"code": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Code"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "IdentifyUserOutput",
"type": "object"
}
```
### Parameters
Group classification (e.g., "company", "org_id").
Specific group identifier (e.g., "Acme Corp").
Group properties as a JSON object. Use operations like $set, $setOnce, $add, $append, $unset.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"code": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Code"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "GroupIdentifyOutput",
"type": "object"
}
```
### Parameters
User ID, Device ID, or Amplitude ID to search for.
### Response
```json
{
"$defs": {
"UserSearchMatch": {
"additionalProperties": false,
"description": "A single user-search match entry.",
"properties": {
"amplitude_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Amplitude Id"
},
"user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User Id"
}
},
"title": "UserSearchMatch",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"matches": {
"items": {
"$ref": "#/$defs/UserSearchMatch"
},
"title": "Matches",
"type": "array"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
}
},
"required": [
"success"
],
"title": "UserSearchOutput",
"type": "object"
}
```
### Parameters
Amplitude internal user ID.
Offset for pagination (default 0).
Maximum number of events to return (default 1000, max 1000).
Sort direction: "latest" or "earliest" (default: latest).
### Response
```json
{
"$defs": {
"UserActivityEvent": {
"additionalProperties": false,
"description": "A single event in a user's activity stream.",
"properties": {
"event_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Event Type"
},
"event_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Event Time"
},
"event_properties": {
"additionalProperties": true,
"title": "Event Properties",
"type": "object"
},
"user_properties": {
"additionalProperties": true,
"title": "User Properties",
"type": "object"
},
"session_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Session Id"
},
"platform": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Platform"
},
"country": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Country"
},
"city": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "City"
}
},
"title": "UserActivityEvent",
"type": "object"
},
"UserData": {
"additionalProperties": false,
"description": "User metadata returned alongside an activity stream.",
"properties": {
"user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User Id"
},
"canonical_amplitude_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Canonical Amplitude Id"
},
"num_events": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Num Events"
},
"num_sessions": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Num Sessions"
},
"platform": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Platform"
},
"country": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Country"
}
},
"title": "UserData",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"events": {
"items": {
"$ref": "#/$defs/UserActivityEvent"
},
"title": "Events",
"type": "array"
},
"user_data": {
"anyOf": [
{
"$ref": "#/$defs/UserData"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UserActivityOutput",
"type": "object"
}
```
### Parameters
External user ID (required if no device_id).
Device ID (required if no user_id).
Include Amplitude user properties (default: false). (Default: `false`)
Include cohort IDs the user belongs to (default: false). (Default: `false`)
Include computed user properties (default: false). (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User Id"
},
"device_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Device Id"
},
"amp_props": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Amp Props"
},
"cohort_ids": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Cohort Ids"
},
"computations": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Computations"
}
},
"required": [
"success"
],
"title": "UserProfileOutput",
"type": "object"
}
```
### Parameters
Event type name to analyze.
Start date in YYYYMMDD format.
End date in YYYYMMDD format.
Metric type: uniques, totals, pct_dau, average, histogram, sums, value_avg, or formula (default: uniques).
Time interval: 1 (daily), 7 (weekly), or 30 (monthly).
Property name to group by (prefix custom user properties with "gp:").
Maximum number of group-by values (max 1000).
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"series": {
"items": {},
"title": "Series",
"type": "array"
},
"series_labels": {
"items": {},
"title": "Series Labels",
"type": "array"
},
"series_collapsed": {
"items": {},
"title": "Series Collapsed",
"type": "array"
},
"x_values": {
"items": {
"type": "string"
},
"title": "X Values",
"type": "array"
}
},
"required": [
"success"
],
"title": "EventSegmentationOutput",
"type": "object"
}
```
### Parameters
Start date in YYYYMMDD format.
End date in YYYYMMDD format.
Metric type: "active" or "new" (default: active).
Time interval: 1 (daily), 7 (weekly), or 30 (monthly).
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"series": {
"items": {},
"title": "Series",
"type": "array"
},
"series_meta": {
"items": {
"type": "string"
},
"title": "Series Meta",
"type": "array"
},
"x_values": {
"items": {
"type": "string"
},
"title": "X Values",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetActiveUsersOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"series": {
"items": {},
"title": "Series",
"type": "array"
},
"series_labels": {
"items": {
"type": "string"
},
"title": "Series Labels",
"type": "array"
},
"x_values": {
"items": {
"type": "string"
},
"title": "X Values",
"type": "array"
}
},
"required": [
"success"
],
"title": "RealtimeActiveUsersOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"ProjectEvent": {
"additionalProperties": false,
"description": "A single event type listed for the project.",
"properties": {
"value": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"totals": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Totals"
},
"hidden": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Hidden"
},
"deleted": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted"
}
},
"title": "ProjectEvent",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"events": {
"items": {
"$ref": "#/$defs/ProjectEvent"
},
"title": "Events",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListEventsOutput",
"type": "object"
}
```
### Parameters
Start date in YYYYMMDD format.
End date in YYYYMMDD format.
Metric: 0 (ARPU), 1 (ARPPU), 2 (Total Revenue), 3 (Paying Users).
Time interval: 1 (daily), 7 (weekly), or 30 (monthly).
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"series": {
"items": {},
"title": "Series",
"type": "array"
},
"series_labels": {
"items": {
"type": "string"
},
"title": "Series Labels",
"type": "array"
},
"x_values": {
"items": {
"type": "string"
},
"title": "X Values",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetRevenueOutput",
"type": "object"
}
```
## Limits & Quotas
- HTTP V2 ingestion: limit uploads to 100 batches/second and 1000 events/second.
- Dashboard REST API analytics endpoints are subject to per-project rate limits and cost thresholds.
- `user_activity` returns at most 1000 events per call (use `offset` to page).
- Error model: non-2xx responses (and missing credentials) are returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Amplitude](https://amplitude.com)
---
# Apify Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/apify
Web scraping, automation, and data extraction platform via the Apify REST API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/apify/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Apify** to any ModuleX agent or workflow. Web scraping, automation, and data extraction platform via the Apify REST API (`api.apify.com/v2`).
**Categories**: Web Search & Scraping · Developer Tools & Infrastructure · Automation · **Auth**: API Token · **Actions**: 7
## Authentication
### API Token
Authenticate using your Apify API token
Go to https://console.apify.com/account/integrations
Copy your Personal API token
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| API Token | Your Apify API token from the Integrations page | Yes | `apify_api_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
The Actor ID or tilde-separated owner/name identifier (e.g. 'apify~web-scraper')
JSON object with the input for the Actor run
Specifies the Actor build to run. If not provided, the default build is used.
If true, returns immediately with run metadata. If false, waits for completion. (Default: `true`)
Optional timeout for the run, in seconds
Memory limit for the run, in megabytes (power of 2, min 128)
The maximum number of items that the Actor run should return
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"run_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Run Id"
},
"act_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Act Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"started_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Started At"
},
"dataset_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Dataset Id"
},
"key_value_store_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Key Value Store Id"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "RunActorOutput",
"type": "object"
}
```
### Parameters
The ID of the task to run
Optional JSON string to override the default input for the task run
Optional timeout for the run, in seconds
Memory limit for the run, in megabytes (power of 2, min 128)
Specifies the Actor build to run (build tag or number)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"run_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Run Id"
},
"act_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Act Id"
},
"task_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Task Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"started_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Started At"
},
"dataset_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Dataset Id"
},
"key_value_store_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Key Value Store Id"
}
},
"required": [
"success"
],
"title": "RunTaskOutput",
"type": "object"
}
```
### Parameters
The ID of the task to run
Optional timeout for the run, in seconds
Memory limit for the run, in megabytes (power of 2, min 128)
Specifies the Actor build to run (build tag or number)
The maximum number of dataset items to return (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"run_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Run Id"
},
"act_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Act Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"started_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Started At"
},
"finished_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Finished At"
},
"dataset_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Dataset Id"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "RunTaskSynchronouslyOutput",
"type": "object"
}
```
### Parameters
The ID of the dataset to retrieve items from
The number of records to skip before returning results (Default: `0`)
The maximum number of items to return (Default: `100`)
Return only non-empty items and skip hidden fields (fields starting with #)
Comma-separated list of field names to include in results
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetDatasetItemsOutput",
"type": "object"
}
```
### Parameters
The ID of the key-value store
The key of the record to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"content_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Type"
},
"data": {
"anyOf": [
{},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetKvsRecordOutput",
"type": "object"
}
```
### Parameters
The URL of the web page to scrape
Crawling engine: 'playwright:firefox' (stealthy), 'playwright:chrome', 'cheerio' (fast, static only), 'playwright:adaptive' (auto-switches) (Default: `playwright:firefox`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
},
"html": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Html"
},
"markdown": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Markdown"
}
},
"required": [
"success"
],
"title": "ScrapeSingleUrlOutput",
"type": "object"
}
```
### Parameters
The ID of the key-value store
The key of the record to create or update
The value to store. Valid JSON strings are stored as JSON; otherwise as plain text.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"store_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Store Id"
},
"key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Key"
},
"content_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Type"
}
},
"required": [
"success"
],
"title": "SetKeyValueStoreRecordOutput",
"type": "object"
}
```
## Limits & Quotas
- Rate limits depend on Apify plan: Free tier has limited concurrent runs; paid plans scale to hundreds.
- Actor runs are billed by compute units (CU) based on memory and duration.
- Synchronous run endpoints have a default server timeout of 300 seconds.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Apify](https://apify.com)
---
# Apollo.io Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/apollo-io
B2B sales intelligence platform with 210M+ contacts and 35M+ companies. Full CRM capabilities including enrichment, prospecting, contacts, accounts, deals, sequences, and tasks.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/apollo_io/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Apollo.io** to any ModuleX agent or workflow. B2B sales intelligence integration: full CRM CRUD + enrichment + prospecting + sequences + tasks against `api.apollo.io/api/v1`. **Largest integration in the package by action count** (27 actions).
**Categories**: Sales · CRM & Customer · Sales · Customer Support · **Auth**: API Key · **Actions**: 28
## Authentication
### API Key Authentication
Authenticate using your Apollo.io API key. Some endpoints require master API key.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Apollo.io API Key | Your Apollo.io API key for authentication | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
First name
Last name
Full name
Email address
Employer name
Employer domain
LinkedIn profile URL
Include personal emails (Default: `false`)
Include phone numbers (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PeopleEnrichmentOutput",
"type": "object"
}
```
### Parameters
List of person detail dicts (max 10)
Include personal emails (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "BulkPeopleEnrichmentOutput",
"type": "object"
}
```
### Parameters
Company domain (e.g. 'apollo.io')
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "OrganizationEnrichmentOutput",
"type": "object"
}
```
### Parameters
List of company domains (max 10)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "BulkOrganizationEnrichmentOutput",
"type": "object"
}
```
### Parameters
Job titles to search
Seniority levels
Person locations
Company HQ locations
Company domains
Apollo organization IDs
Employee ranges
Email verification status
Keyword search
Page number (Default: `1`)
Results per page (Default: `25`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PeopleSearchOutput",
"type": "object"
}
```
### Parameters
Company name
HQ locations
Exclude locations
Employee ranges
Min revenue
Max revenue
Technologies
Industry keywords
Page number (Default: `1`)
Results per page (Default: `25`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "OrganizationSearchOutput",
"type": "object"
}
```
### Parameters
Apollo organization ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "OrganizationJobPostingsOutput",
"type": "object"
}
```
### Parameters
Contact email
First name
Last name
Job title
Company name
Link to existing account
Phone number
LinkedIn URL
Address
Labels/tags
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "CreateContactOutput",
"type": "object"
}
```
### Parameters
Contact ID to update
New email
New first name
New last name
New job title
New phone
Link to account
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "UpdateContactOutput",
"type": "object"
}
```
### Parameters
Search keywords
Filter by stage
Filter by owner
Page number (Default: `1`)
Results per page (Default: `25`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "SearchContactsOutput",
"type": "object"
}
```
### Parameters
Contact ID to view
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "ViewContactOutput",
"type": "object"
}
```
### Parameters
Account/company name
Company domain
Phone number
Address
Owner user ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "CreateAccountOutput",
"type": "object"
}
```
### Parameters
Account ID to update
New name
New phone
New address
New owner ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "UpdateAccountOutput",
"type": "object"
}
```
### Parameters
Search by name
Filter by stage
Filter by owner
Page number (Default: `1`)
Results per page (Default: `25`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "SearchAccountsOutput",
"type": "object"
}
```
### Parameters
Account ID to view
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "ViewAccountOutput",
"type": "object"
}
```
### Parameters
Deal name
Deal stage ID
Deal amount
Associated account ID
Associated contact IDs
Deal owner user ID
Expected close date (YYYY-MM-DD)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "CreateDealOutput",
"type": "object"
}
```
### Parameters
Deal ID to update
New name
New stage ID
New amount
New owner ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "UpdateDealOutput",
"type": "object"
}
```
### Parameters
Page number (Default: `1`)
Results per page (Default: `25`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "ListDealsOutput",
"type": "object"
}
```
### Parameters
Deal ID to view
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "ViewDealOutput",
"type": "object"
}
```
### Parameters
Sequence name to search
Page number (Default: `1`)
Results per page (Default: `25`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "SearchSequencesOutput",
"type": "object"
}
```
### Parameters
Sequence ID
Contact IDs to enroll
Email campaign ID
Sender email account ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "AddContactsToSequenceOutput",
"type": "object"
}
```
### Parameters
Task name/subject
Due date (YYYY-MM-DD)
Priority ('low', 'normal', 'high') (Default: `normal`)
Associated contact ID
Associated account ID
Assigned user ID
Task notes
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "CreateTaskOutput",
"type": "object"
}
```
### Parameters
Status filter
Filter by assigned users
Page number (Default: `1`)
Results per page (Default: `25`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "SearchTasksOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "GetApiUsageOutput",
"type": "object"
}
```
### Parameters
Page number (Default: `1`)
Results per page (Default: `25`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "ListUsersOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "ListContactStagesOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "ListAccountStagesOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "ListDealStagesOutput",
"type": "object"
}
```
## Limits & Quotas
- `per_page` clamped at 100 (Apollo's cap on most search endpoints).
- Bulk-enrichment actions clamp input to 10 items per request
(Apollo's cap).
- Enrichment-class actions consume Apollo credits; CRUD on
contacts/accounts/deals does NOT.
- Domain helpers strip `https://` / `www.` / paths so callers can
pass full URLs or bare hostnames interchangeably.
## Related integrations
## Links
- [Apollo.io](https://www.apollo.io)
---
# Amazon Web Services Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/aws
Interact with AWS services including DynamoDB, S3, Lambda, SNS, SQS, EventBridge, CloudWatch Logs, and Redshift.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/aws/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Amazon Web Services** to any ModuleX agent or workflow. Interact with AWS services including DynamoDB, S3, Lambda, SNS, SQS, EventBridge, CloudWatch Logs, and Redshift via the AWS SDK (`boto3`).
**Categories**: Cloud Infrastructure · Developer Tools & Infrastructure · Data Storage · **Auth**: AWS Access Key · **Actions**: 21
## Authentication
### AWS Access Key
Authenticate using an AWS access key ID and secret access key.
Sign in to the AWS Management Console.
Go to IAM > Users > your user > Security credentials.
Create an access key and save both the Access Key ID and Secret Access Key.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Access Key ID | Your AWS Access Key ID | Yes | `AKIAIOSFODNN7EXAMPLE` |
| Secret Access Key | Your AWS Secret Access Key | Yes | `wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY` |
## Available Actions
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
Name of the CloudWatch log group
Name of the log stream within the log group
The log event message
Unix timestamp in milliseconds for the event
Sequence token from a previous PutLogEvents call (not needed for a new log stream)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"next_sequence_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Sequence Token"
},
"rejected_log_events_info": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Rejected Log Events Info"
}
},
"required": [
"success"
],
"title": "CloudwatchLogsPutLogEventOutput",
"type": "object"
}
```
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
Name of the table to create
Name of the partition key attribute
Data type of the partition key: S (string), N (number), or B (binary)
Name of the sort key attribute (optional)
Data type of the sort key: S (string), N (number), or B (binary)
Billing mode: PROVISIONED or PAY_PER_REQUEST
Read capacity units (required when billing_mode is PROVISIONED)
Write capacity units (required when billing_mode is PROVISIONED)
Whether DynamoDB Streams is enabled
Stream view type: KEYS_ONLY, NEW_IMAGE, OLD_IMAGE, or NEW_AND_OLD_IMAGES
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"table_description": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Table Description"
}
},
"required": [
"success"
],
"title": "DynamodbCreateTableOutput",
"type": "object"
}
```
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
PartiQL statement to execute
List of parameter values for the PartiQL statement (strings)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "DynamodbExecuteStatementOutput",
"type": "object"
}
```
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
Name of the DynamoDB table
Item key in DynamoDB JSON format, e.g. {"id": {"S": "123"}}
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"item": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Item"
}
},
"required": [
"success"
],
"title": "DynamodbGetItemOutput",
"type": "object"
}
```
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
Name of the DynamoDB table
Item in DynamoDB JSON format, e.g. {"id": {"S": "123"}, "name": {"S": "foo"}}
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"attributes": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Attributes"
}
},
"required": [
"success"
],
"title": "DynamodbPutItemOutput",
"type": "object"
}
```
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
Name of the DynamoDB table
Key condition expression, e.g. partitionKey = :pk AND sortKey > :sk
Comma-separated attribute names to retrieve
Substitution tokens for attribute names, e.g. {"#n": "name"}
Substitution values in DynamoDB JSON format, e.g. {":pk": {"S": "val"}}
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"scanned_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Scanned Count"
}
},
"required": [
"success"
],
"title": "DynamodbQueryOutput",
"type": "object"
}
```
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
Name of the DynamoDB table
Comma-separated attribute names to retrieve
Filter expression to apply after scanning
Substitution tokens for attribute names, e.g. {"#n": "name"}
Substitution values in DynamoDB JSON format, e.g. {":val": {"S": "x"}}
Maximum number of items to evaluate
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"scanned_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Scanned Count"
}
},
"required": [
"success"
],
"title": "DynamodbScanOutput",
"type": "object"
}
```
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
Name of the DynamoDB table
Item key in DynamoDB JSON format, e.g. {"id": {"S": "123"}}
Update expression, e.g. SET #n = :val
Substitution tokens for attribute names, e.g. {"#n": "name"}
Substitution values in DynamoDB JSON format, e.g. {":val": {"S": "x"}}
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"attributes": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Attributes"
}
},
"required": [
"success"
],
"title": "DynamodbUpdateItemOutput",
"type": "object"
}
```
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
Name of the DynamoDB table
Billing mode: PROVISIONED or PAY_PER_REQUEST
Read capacity units (required when billing_mode is PROVISIONED)
Write capacity units (required when billing_mode is PROVISIONED)
Whether DynamoDB Streams is enabled
Stream view type: KEYS_ONLY, NEW_IMAGE, OLD_IMAGE, or NEW_AND_OLD_IMAGES
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"table_description": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Table Description"
}
},
"required": [
"success"
],
"title": "DynamodbUpdateTableOutput",
"type": "object"
}
```
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
Name of the EventBridge event bus
JSON object to send as the event detail
Free-form string (max 128 chars) identifying the event type (Default: `modulex.event`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"failed_entry_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Failed Entry Count"
},
"entries": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Entries",
"type": "array"
}
},
"required": [
"success"
],
"title": "EventbridgeSendEventOutput",
"type": "object"
}
```
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
Name for the Lambda function
IAM Role ARN for the function execution role
Function source code (Python handler)
Lambda runtime: python3.12, python3.11, nodejs20.x, etc. (Default: `python3.12`)
Handler entrypoint (e.g. lambda_function.lambda_handler) (Default: `lambda_function.lambda_handler`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"function_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Function Name"
},
"function_arn": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Function Arn"
},
"runtime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Runtime"
},
"role": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Role"
},
"handler": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Handler"
},
"code_size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Code Size"
},
"last_modified": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Modified"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
}
},
"required": [
"success"
],
"title": "LambdaCreateFunctionOutput",
"type": "object"
}
```
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
Name or ARN of the Lambda function to invoke
JSON object to send as the invocation payload
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"status_code": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Status Code"
},
"payload": {
"default": null,
"title": "Payload"
},
"function_error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Function Error"
},
"executed_version": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Executed Version"
}
},
"required": [
"success"
],
"title": "LambdaInvokeFunctionOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"RegionInfo": {
"additionalProperties": false,
"properties": {
"region_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Region Name"
},
"endpoint": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Endpoint"
},
"opt_in_status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Opt In Status"
}
},
"title": "RegionInfo",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"regions": {
"items": {
"$ref": "#/$defs/RegionInfo"
},
"title": "Regions",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListRegionOptionsOutput",
"type": "object"
}
```
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
Name of the Redshift Serverless workgroup
Database name
Schema name
Table name
List of column names (strings), e.g. ["id", "name"]
List of row arrays, e.g. [[1, "Alice"], [2, "Bob"]]
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"statement_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Statement Id"
}
},
"required": [
"success"
],
"title": "RedshiftCreateRowsOutput",
"type": "object"
}
```
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
Name of the Redshift Serverless workgroup
Database name
Schema name
Table name
WHERE clause with named parameters, e.g. id = :id
Named parameter values, e.g. {"id": 1}
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"statement_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Statement Id"
}
},
"required": [
"success"
],
"title": "RedshiftDeleteRowsOutput",
"type": "object"
}
```
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
Name of the Redshift Serverless workgroup
Database name
List of column names to retrieve (strings); omit for SELECT *
FROM clause, e.g. schema_name.table_name
WHERE clause with named parameters, e.g. id = :id
ORDER BY clause, e.g. column_name ASC
Maximum number of rows to return (Default: `10`)
Named parameter values, e.g. {"id": 1}
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"records": {
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"type": "array"
},
"title": "Records",
"type": "array"
},
"total_num_rows": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Num Rows"
},
"column_metadata": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Column Metadata",
"type": "array"
}
},
"required": [
"success"
],
"title": "RedshiftQueryDatabaseOutput",
"type": "object"
}
```
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
Name of the Redshift Serverless workgroup
Database name
Schema name
Table name
Key-value pairs to set, e.g. {"col1": "new_val"}
WHERE clause with named parameters, e.g. id = :id
Named parameter values, e.g. {"id": 1}
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"statement_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Statement Id"
}
},
"required": [
"success"
],
"title": "RedshiftUpdateRowsOutput",
"type": "object"
}
```
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
S3 bucket name
Object key (path) to generate the URL for
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
}
},
"required": [
"success"
],
"title": "S3GeneratePresignedUrlOutput",
"type": "object"
}
```
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
S3 bucket name
S3 object key (path including filename and extension)
Base64-encoded file content
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"bucket": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Bucket"
},
"key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Key"
}
},
"required": [
"success"
],
"title": "S3UploadBase64AsFileOutput",
"type": "object"
}
```
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
ARN of the SNS topic
Message to publish
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message Id"
}
},
"required": [
"success"
],
"title": "SnsSendMessageOutput",
"type": "object"
}
```
### Parameters
AWS region (e.g. us-east-1, eu-west-1) (Default: `us-east-1`)
URL of the SQS queue
JSON object to send as the message body
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message Id"
},
"md5_of_message_body": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Md5 Of Message Body"
},
"sequence_number": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sequence Number"
}
},
"required": [
"success"
],
"title": "SqsSendMessageOutput",
"type": "object"
}
```
## Limits & Quotas
- AWS service limits vary by service, region, and account. See
[AWS Service Quotas](https://docs.aws.amazon.com/general/latest/gr/aws-service-information.html)
for per-service details.
- DynamoDB: default 40,000 RCU / 40,000 WCU per table (on-demand auto-scales).
- S3: no per-request limit; 3,500 PUT/s and 5,500 GET/s per prefix.
- Lambda: 1,000 concurrent executions (default, adjustable).
- SNS/SQS: region-dependent throughput limits.
- Redshift Data API: 200 active queries per cluster/workgroup.
- Error model: all AWS SDK exceptions are caught and returned as
`success=False` + `error` rather than raising.
## Related integrations
## Links
- [Amazon Web Services](https://aws.amazon.com)
---
# Azure Storage Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/azure-storage
Manage blobs and containers in Microsoft Azure Blob Storage
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/azure_storage/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Azure Storage** to any ModuleX agent or workflow. Manage blobs and containers in Microsoft Azure Blob Storage via the Azure Blob Storage REST API (`https://.blob.core.windows.net`).
**Categories**: Cloud Infrastructure · Storage · **Auth**: Microsoft OAuth2 · **Actions**: 4
## Authentication
### Microsoft OAuth2
Connect using Microsoft OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Azure AD App Registration Client ID | Yes | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
| Client Secret | Azure AD App Registration Client Secret | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
| Storage Account Name | Azure Storage account name (appears in the blob endpoint URL) | Yes | `mystorageaccount` |
#### OAuth Configuration
- **Authorization URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/authorize`
- **Token URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/token`
- **Scopes**: `https://storage.azure.com/user_impersonation`, `offline_access`
## Available Actions
### Parameters
Name of the container to create (lowercase, alphanumeric and hyphens only)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "CreateContainerOutput",
"type": "object"
}
```
### Parameters
Name of the container holding the blob
Name of the blob to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "DeleteBlobOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"containers": {
"items": {
"type": "string"
},
"title": "Containers",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListContainersOutput",
"type": "object"
}
```
### Parameters
Name of the target container
Name for the blob in the container
Publicly accessible URL of the file to upload
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "UploadBlobOutput",
"type": "object"
}
```
## Limits & Quotas
- Azure Storage limits vary by account type and tier; see
[Azure Storage scalability targets](https://learn.microsoft.com/en-us/azure/storage/common/scalability-targets-standard-account).
- Blob REST API requests are subject to per-account throughput limits
(up to 20,000 requests/sec for general-purpose v2 accounts).
- Error model: non-2xx responses are caught and returned as
`success=False` + `error` rather than raising.
## Related integrations
## Links
- [Azure Storage](https://azure.microsoft.com/en-us/products/storage/blobs)
---
# Bloomerang Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/bloomerang
Nonprofit donor management and fundraising CRM platform
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/bloomerang/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Bloomerang** to any ModuleX agent or workflow. Nonprofit donor management and fundraising CRM platform integration against the Bloomerang REST API (`api.bloomerang.co/v2`).
**Categories**: CRM · Nonprofit · Fundraising · **Auth**: API Key · **Actions**: 3
## Authentication
### API Key Authentication
Authenticate using your Bloomerang API key
Log in to your Bloomerang account
Navigate to Settings > API Keys
Create a new API key or copy your existing one
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Bloomerang API Key | Your Bloomerang API key | Yes | `-` |
## Available Actions
### Parameters
Constituent type. Valid values: Individual, Organization
First name of the constituent (used when type is Individual)
Last name of the constituent (used when type is Individual)
Organization name (used when type is Organization)
Status of the constituent. Valid values: Active, Inactive, Deceased
Middle name of the constituent
Prefix/title. Valid values: Mr., Mrs., Ms., Mx., Dr., Rev., etc.
Suffix. Valid values: Jr., Sr., II, III, IV, V, Ph.D., M.D., Esq., etc.
Job title of the constituent
Gender. Valid values: Male, Female, Other
Birth date of the constituent (ISO format YYYY-MM-DD)
Employer of the constituent
Website URL of the constituent
Facebook page URL of the constituent
Twitter/X handle of the constituent
LinkedIn page URL of the constituent
Preferred communication channel. Valid values: Email, Phone, Text Message, Mail
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Name"
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Name"
},
"full_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Full Name"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
}
},
"required": [
"success"
],
"title": "CreateConstituentOutput",
"type": "object"
}
```
### Parameters
ID of the constituent (donor)
Date of the donation (ISO format YYYY-MM-DD)
Donation amount as a numeric string
ID of the fund for the donation
Payment method. Valid values: None, Cash, Check, CreditCard, Eft, InKind, ApplePay, GooglePay, PayPal, Venmo
ID of the campaign for the donation
ID of the appeal for the donation
Note for the donation
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"amount": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Amount"
},
"date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Date"
}
},
"required": [
"success"
],
"title": "CreateDonationOutput",
"type": "object"
}
```
### Parameters
ID of the constituent
Date of the interaction (ISO format YYYY-MM-DD)
Subject of the interaction
Channel of the interaction. Valid values: Email, InPerson, Mail, MassEmail, Other, Phone, SocialMedia, TextMessage, VideoCall, Webinar, Website
Purpose of the interaction. Valid values: Acknowledgement, ImpactCultivation, Newsletter, Receipt, Solicitation, SpecialEvent, VolunteerActivity, PledgeReminder, Welcome, Other
Note for the interaction
Whether the interaction was initiated by the constituent
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"channel": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Channel"
}
},
"required": [
"success"
],
"title": "AddInteractionOutput",
"type": "object"
}
```
## Limits & Quotas
- No publicly documented rate limits for the Bloomerang REST API v2.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Bloomerang](https://bloomerang.co)
---
# Brandfetch Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/brandfetch
Integrate Brandfetch into your workflow. Retrieve brand logos, colors, fonts, and company data by domain, ticker, or name search.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/brandfetch/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Brandfetch** to any ModuleX agent or workflow. Look up brand assets, logos, colors, fonts, and company firmographics by domain, ticker, ISIN, or crypto symbol — and resolve brand names to domains — against the Brandfetch REST API (`api.brandfetch.io`).
**Categories**: Sales · Enrichment · Marketing · **Auth**: API Key · **Actions**: 2
## Authentication
### API Key Authentication
Authenticate using your Brandfetch API key
Sign up or log in at https://developers.brandfetch.com
Open your dashboard and locate your API key
Copy the API key and paste it below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Brandfetch API Key | Your Brandfetch API key from the developer dashboard | Yes | `-` |
## Available Actions
### Parameters
Brand identifier: domain (nike.com), stock ticker (NKE), ISIN (US6541061031), or crypto symbol (BTC)
### Response
```json
{
"$defs": {
"BrandColor": {
"additionalProperties": false,
"description": "A brand color with its hex value and role.",
"properties": {
"hex": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hex"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"brightness": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Brightness"
}
},
"title": "BrandColor",
"type": "object"
},
"BrandFont": {
"additionalProperties": false,
"description": "A brand font with its name, role, and origin.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"origin": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Origin"
},
"origin_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Origin Id"
},
"weights": {
"items": {
"type": "integer"
},
"title": "Weights",
"type": "array"
}
},
"title": "BrandFont",
"type": "object"
},
"BrandLink": {
"additionalProperties": false,
"description": "A single social/website link entry.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
}
},
"title": "BrandLink",
"type": "object"
},
"BrandLogo": {
"additionalProperties": false,
"description": "A logo asset with its theme and available formats.",
"properties": {
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"theme": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Theme"
},
"formats": {
"items": {
"$ref": "#/$defs/BrandLogoFormat"
},
"title": "Formats",
"type": "array"
}
},
"title": "BrandLogo",
"type": "object"
},
"BrandLogoFormat": {
"additionalProperties": false,
"description": "One downloadable format for a logo asset.",
"properties": {
"src": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Src"
},
"format": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Format"
},
"width": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Width"
},
"height": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Height"
},
"background": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Background"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
}
},
"title": "BrandLogoFormat",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Domain"
},
"claimed": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Claimed"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"long_description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Long Description"
},
"links": {
"items": {
"$ref": "#/$defs/BrandLink"
},
"title": "Links",
"type": "array"
},
"logos": {
"items": {
"$ref": "#/$defs/BrandLogo"
},
"title": "Logos",
"type": "array"
},
"colors": {
"items": {
"$ref": "#/$defs/BrandColor"
},
"title": "Colors",
"type": "array"
},
"fonts": {
"items": {
"$ref": "#/$defs/BrandFont"
},
"title": "Fonts",
"type": "array"
},
"company": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Company"
},
"quality_score": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Quality Score"
},
"is_nsfw": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Nsfw"
}
},
"required": [
"success"
],
"title": "GetBrandOutput",
"type": "object"
}
```
### Parameters
Company or brand name to search for
### Response
```json
{
"$defs": {
"SearchResultItem": {
"additionalProperties": false,
"description": "A single brand match returned by ``search``.",
"properties": {
"brand_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Brand Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Domain"
},
"claimed": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Claimed"
},
"icon": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Icon"
}
},
"title": "SearchResultItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"results": {
"items": {
"$ref": "#/$defs/SearchResultItem"
},
"title": "Results",
"type": "array"
},
"total_results": {
"default": 0,
"title": "Total Results",
"type": "integer"
}
},
"required": [
"success"
],
"title": "SearchOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limit**: approximately 30 requests/minute.
- **Brand API** (`get_brand`): metered per request on paid tiers;
requests for the `brandfetch.com` domain are free.
- **Brand Search API** (`search`): free under fair use (up to ~500,000
requests/month).
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising. Plan for
retries on the agent side based on the error string.
## Related integrations
## Links
- [Brandfetch](https://brandfetch.com)
---
# Browser Use Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/browser-use
AI-powered cloud browser automation via the Browser Use API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/browser_use/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Browser Use** to any ModuleX agent or workflow. AI-powered cloud browser automation via the Browser Use REST API (`api.browser-use.com/api/v3`). Create agent sessions to perform web tasks, manage standalone browser sessions via CDP, and organize persistent profiles and workspaces.
**Categories**: AI & Machine Learning · Automation · AI · Developer Tools & Infrastructure · **Auth**: API Key · **Actions**: 25
## Authentication
### API Key Authentication
Authenticate using your Browser Use API key
Go to https://cloud.browser-use.com and sign in
Navigate to your project settings or API Keys section
Create a new API key or copy your existing one
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Browser Use API Key | Your Browser Use API key from cloud.browser-use.com | Yes | `bu_xxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
Natural-language instruction for the agent
Browser Use agent model. Allowed values: claude-sonnet-4.6, claude-opus-4.6, gemini-3-flash, bu-mini, bu-max, bu-ultra (Default: `claude-sonnet-4.6`)
ID of an existing session to dispatch a follow-up task to
If true, the session stays idle after the task completes so it can accept follow-up tasks (Default: `false`)
Maximum total session cost in USD. Example: 1.50
ID of a Browser Use profile to use
ID of a Browser Use workspace to attach
Lowercase proxy country code for browser traffic. Examples: us, de, jp. Enter none to disable proxy (Default: `us`)
Optional JSON Schema for structured output
If true, the agent can create scheduled tasks tied to your project (Default: `false`)
Key-value pairs available to the agent through secure placeholders. Keys are visible to the model; values are hidden
If true, Browser Use records the browser session and returns recording URLs after completion (Default: `false`)
If true, enables built-in Browser Use agent skills such as file management (Default: `true`)
If true, provisions a temporary email inbox for the session (Default: `true`)
Controls deterministic script caching. Allowed values: auto, enabled, disabled (Default: `auto`)
If true, uses your configured LLM provider key instead of Browser Use managed keys (Default: `false`)
When script caching is active, validates cached script output and reruns the full agent if the result looks incorrect (Default: `true`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"task": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Task"
},
"live_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Live Url"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateSessionOutput",
"type": "object"
}
```
### Parameters
ID of the Browser Use agent session
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"task": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Task"
},
"output": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Output"
},
"live_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Live Url"
},
"screenshot_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Screenshot Url"
},
"cost": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Cost"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetSessionOutput",
"type": "object"
}
```
### Parameters
Page number to fetch. The first page is 1 (Default: `1`)
Number of records to return per page. Maximum: 100 (Default: `20`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"sessions": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Sessions",
"type": "array"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
}
},
"required": [
"success"
],
"title": "ListSessionsOutput",
"type": "object"
}
```
### Parameters
ID of the Browser Use agent session to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "DeleteSessionOutput",
"type": "object"
}
```
### Parameters
ID of the Browser Use agent session
Use task to stop only the current task and keep the session alive, or session to destroy the sandbox entirely. Allowed values: task, session (Default: `session`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "StopSessionOutput",
"type": "object"
}
```
### Parameters
ID of the Browser Use agent session
Return messages after this message ID cursor
Return messages before this message ID cursor
Maximum number of messages to return. Maximum: 100 (Default: `10`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"messages": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Messages",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListSessionMessagesOutput",
"type": "object"
}
```
### Parameters
ID of a Browser Use profile
Lowercase proxy country code for browser traffic. Examples: us, de, jp. Enter none to disable proxy (Default: `us`)
Session timeout in minutes. Supported range: 1 to 240 (Default: `60`)
Custom browser screen width in pixels. Supported range: 320 to 6144
Custom browser screen height in pixels. Supported range: 320 to 3456
Whether to allow browser resizing during the session (Default: `false`)
Custom proxy object with host, port, username, and password fields. Requires an active subscription
If true, records the browser session (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"live_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Live Url"
},
"cdp_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cdp Url"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateBrowserSessionOutput",
"type": "object"
}
```
### Parameters
ID of the Browser Use browser session
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"live_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Live Url"
},
"cdp_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cdp Url"
},
"timeout": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Timeout"
},
"cost": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Cost"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetBrowserSessionOutput",
"type": "object"
}
```
### Parameters
Number of records to return per page. Maximum: 100 (Default: `20`)
Page number to fetch. The first page is 1 (Default: `1`)
Filter browser sessions by status. Allowed values: active, stopped
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
},
"total_items": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Items"
}
},
"required": [
"success"
],
"title": "ListBrowserSessionsOutput",
"type": "object"
}
```
### Parameters
ID of the Browser Use browser session
Action to perform on the browser session. Currently supported value: stop (Default: `stop`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "UpdateBrowserSessionOutput",
"type": "object"
}
```
### Parameters
Optional profile name. Maximum length: 100 characters
Optional internal user identifier from your system. Maximum length: 255 characters
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateProfileOutput",
"type": "object"
}
```
### Parameters
ID of the Browser Use profile
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User Id"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetProfileOutput",
"type": "object"
}
```
### Parameters
Number of records to return per page. Maximum: 100 (Default: `20`)
Page number to fetch. The first page is 1 (Default: `1`)
Search query for profile name or user ID. Maximum length: 200 characters
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
},
"total_items": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Items"
}
},
"required": [
"success"
],
"title": "ListProfilesOutput",
"type": "object"
}
```
### Parameters
ID of the Browser Use profile to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "DeleteProfileOutput",
"type": "object"
}
```
### Parameters
ID of the Browser Use profile
Updated profile name. Maximum length: 100 characters
Updated internal user identifier. Maximum length: 255 characters
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User Id"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "UpdateProfileOutput",
"type": "object"
}
```
### Parameters
Optional workspace name. Maximum length: 100 characters
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateWorkspaceOutput",
"type": "object"
}
```
### Parameters
ID of the Browser Use workspace
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetWorkspaceOutput",
"type": "object"
}
```
### Parameters
Number of records to return per page. Maximum: 100 (Default: `20`)
Page number to fetch. The first page is 1 (Default: `1`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
},
"total_items": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Items"
}
},
"required": [
"success"
],
"title": "ListWorkspacesOutput",
"type": "object"
}
```
### Parameters
ID of the Browser Use workspace to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "DeleteWorkspaceOutput",
"type": "object"
}
```
### Parameters
ID of the Browser Use workspace
Updated workspace name. Maximum length: 100 characters
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "UpdateWorkspaceOutput",
"type": "object"
}
```
### Parameters
ID of the Browser Use workspace
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"size_bytes": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size Bytes"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetWorkspaceSizeOutput",
"type": "object"
}
```
### Parameters
ID of the Browser Use workspace
Optional directory prefix to list. Example: reports/
Maximum number of files to return. Maximum: 100 (Default: `50`)
Pagination cursor from a previous response
If true, include presigned download URLs for files (Default: `false`)
If true, list only immediate files and folders at the prefix (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"files": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Files",
"type": "array"
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cursor"
}
},
"required": [
"success"
],
"title": "ListWorkspaceFilesOutput",
"type": "object"
}
```
### Parameters
ID of the Browser Use workspace
Relative workspace file path to delete. Example: reports/data.csv
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "DeleteWorkspaceFileOutput",
"type": "object"
}
```
### Parameters
ID of the Browser Use workspace
Optional directory prefix to upload into. Example: uploads/
JSON array of file metadata objects. Each object has name (required), contentType (optional), and size (optional integer). 1 to 10 files per request
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"files": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Files",
"type": "array"
}
},
"required": [
"success"
],
"title": "UploadWorkspaceFilesOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetAccountBillingOutput",
"type": "object"
}
```
## Limits & Quotas
- No publicly documented request rate limits at the time of writing.
- Agent sessions are billed by runtime and model usage; `max_cost_usd`
parameter available to cap spend per session.
- Browser sessions are billed by runtime and can run up to 4 hours.
- Error model: non-2xx responses and timeouts are caught and returned
as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Browser Use](https://browser-use.com)
---
# Browserbase Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/browserbase
Cloud browser infrastructure for running and managing headless browser sessions
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/browserbase/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Browserbase** to any ModuleX agent or workflow. Cloud browser infrastructure for running and managing headless browser sessions via the Browserbase REST API (`api.browserbase.com/v1`).
**Categories**: Developer Tools & Infrastructure · Automation · Browser · **Auth**: API Key · **Actions**: 3
## Authentication
### API Key Authentication
Authenticate using your Browserbase API key
Go to https://www.browserbase.com and sign in
Navigate to Settings > API Keys
Create a new API key or copy your existing one
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Browserbase API Key | Your Browserbase API key from the settings page | Yes | `bb_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
The ID of the Browserbase project
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"project_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Project Id"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
}
},
"required": [
"success"
],
"title": "CreateContextOutput",
"type": "object"
}
```
### Parameters
The ID of the Browserbase project
The uploaded Extension ID to load in the session
Settings for the session (e.g. fingerprint, viewport). See Browserbase docs for schema.
Duration in seconds after which the session will automatically end. Min: 60, Max: 21600.
Set to true to keep the session alive even after disconnections
Array of proxy configuration objects. Each element should have type and optional geolocation fields.
The region where the session should run. One of: us-west-2, us-east-1, eu-central-1, ap-southeast-1.
Arbitrary user metadata to attach to the session
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"project_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Project Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"region": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Region"
},
"connect_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Connect Url"
}
},
"required": [
"success"
],
"title": "CreateSessionOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"ProjectSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
}
},
"title": "ProjectSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"projects": {
"items": {
"$ref": "#/$defs/ProjectSummary"
},
"title": "Projects",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListProjectsOutput",
"type": "object"
}
```
## Limits & Quotas
- Rate limits are not publicly documented by Browserbase; contact their support for enterprise limits.
- Session timeout range: 60–21600 seconds.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Browserbase](https://www.browserbase.com)
---
# Cal.com Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/cal-com
Scheduling and booking management via the Cal.com v2 API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/cal_com/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Cal.com** to any ModuleX agent or workflow. Scheduling and booking management via the Cal.com v2 REST API (`api.cal.com/v2`).
**Categories**: Scheduling & Events · Productivity & Collaboration · Scheduling · Calendar · **Auth**: API Key · **Actions**: 6
## Authentication
### API Key
Authenticate using your Cal.com v2 API key
Sign in to Cal.com at https://app.cal.com
Navigate to Settings > Developer > API Keys
Create a new API key or copy an existing one
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Cal.com API Key | Your Cal.com v2 API key from Settings > Developer > API Keys | Yes | `cal_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
Type of booking: booking, instant, or recurring
Full name of the attendee
Time zone of the attendee, e.g. America/New_York
Booking start time in ISO 8601 UTC format, e.g. 2024-08-13T09:00:00Z
Email address of the attendee
Phone number in international format, e.g. +919876543210
Language for the booking confirmation
ID of the event type (alternative to slug-based identification)
Slug of the event type (use with username or team_slug)
Username of the individual event owner
Team slug for team event type identification
Organization slug for slug-based event type identification
Booking end time in ISO 8601 format
Override the event type default duration in minutes
Additional guest email addresses to invite
Meeting location type: attendeeAddress, attendeeDefined, attendeePhone, integration
Physical address if location is attendeeAddress
Location string if location is attendeeDefined
Phone number if location is attendeePhone
Video conferencing integration if location is integration
Number of occurrences for recurring booking type
Custom key-value metadata, e.g. {"source": "website"}
Responses to custom booking form fields keyed by field slug
Bypass availability checks and allow double-booking
Allow booking outside the event type scheduling window
Required when event type has email verification enabled
### Response
```json
{
"$defs": {
"BookingItem": {
"additionalProperties": false,
"description": "A booking object returned by the Cal.com API.",
"properties": {
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"start": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Start"
},
"end": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "End"
},
"attendees": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Attendees",
"type": "array"
},
"hosts": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Hosts",
"type": "array"
},
"event_type_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Event Type Id"
},
"meeting_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Meeting Url"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location"
}
},
"title": "BookingItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"booking": {
"anyOf": [
{
"$ref": "#/$defs/BookingItem"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateBookingOutput",
"type": "object"
}
```
### Parameters
The UID of the booking to cancel
The reason for cancelling the booking
Whether to cancel all subsequent occurrences of a recurring booking
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
}
},
"required": [
"success"
],
"title": "DeleteBookingOutput",
"type": "object"
}
```
### Parameters
Maximum number of pages to fetch (1-500, default 50)
Filter by status: upcoming, recurring, past, cancelled, unconfirmed
Return bookings that start after this time (ISO 8601)
Return bookings that end before this time (ISO 8601)
Return bookings created after this time (ISO 8601)
Return bookings created before this time (ISO 8601)
Filter bookings by attendee email
Filter bookings by attendee name
Filter bookings by booking UID
Filter bookings by event type ID
Sort bookings by start time: asc or desc
Sort bookings by end time: asc or desc
Sort bookings by creation time: asc or desc
### Response
```json
{
"$defs": {
"BookingItem": {
"additionalProperties": false,
"description": "A booking object returned by the Cal.com API.",
"properties": {
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"start": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Start"
},
"end": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "End"
},
"attendees": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Attendees",
"type": "array"
},
"hosts": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Hosts",
"type": "array"
},
"event_type_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Event Type Id"
},
"meeting_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Meeting Url"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location"
}
},
"title": "BookingItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"bookings": {
"items": {
"$ref": "#/$defs/BookingItem"
},
"title": "Bookings",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetAllBookingsOutput",
"type": "object"
}
```
### Parameters
Start date/time in ISO 8601 format (UTC)
End date/time in ISO 8601 format (UTC)
ID of the event type to get slots for
Slug of the event type (requires username or team_slug)
Username of the individual event owner
List of at least 2 usernames for a dynamic event
Slug of the team for team event type slot lookup
Organization slug for slug-based event type lookup
The time zone for the slot lookup
Override the default slot duration in minutes
Response format: range (start and end) or time (start only)
UID of the booking being rescheduled to exclude from busy calculations
### Response
```json
{
"$defs": {
"GetBookableSlot": {
"additionalProperties": false,
"description": "A single available time slot.",
"properties": {
"time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Time"
},
"start": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Start"
},
"end": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "End"
}
},
"title": "GetBookableSlot",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"slots": {
"additionalProperties": {
"items": {
"$ref": "#/$defs/GetBookableSlot"
},
"type": "array"
},
"title": "Slots",
"type": "object"
}
},
"required": [
"success"
],
"title": "GetBookableSlotsOutput",
"type": "object"
}
```
### Parameters
The UID of the booking to retrieve
### Response
```json
{
"$defs": {
"BookingItem": {
"additionalProperties": false,
"description": "A booking object returned by the Cal.com API.",
"properties": {
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"start": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Start"
},
"end": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "End"
},
"attendees": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Attendees",
"type": "array"
},
"hosts": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Hosts",
"type": "array"
},
"event_type_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Event Type Id"
},
"meeting_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Meeting Url"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location"
}
},
"title": "BookingItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"booking": {
"anyOf": [
{
"$ref": "#/$defs/BookingItem"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetBookingOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"EventTypeOption": {
"additionalProperties": false,
"description": "An event type with its ID and title.",
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Label"
},
"value": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
}
},
"title": "EventTypeOption",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"event_types": {
"items": {
"$ref": "#/$defs/EventTypeOption"
},
"title": "Event Types",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListEventTypeIdOptionsOutput",
"type": "object"
}
```
## Limits & Quotas
- Cal.com does not publicly document rate limits for the v2 API; enterprise plans may have higher thresholds.
- The free tier has a limited number of event types and team members.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Cal.com](https://cal.com)
---
# Calendly Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/calendly
Calendly scheduling platform integration for managing events, invitees, event types, and scheduling links. Automate meeting scheduling workflows and access scheduling data.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/calendly/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Calendly** to any ModuleX agent or workflow. Scheduling-platform integration for Calendly: events, invitees, event types, scheduling links, availability, organization members, groups, and webhook subscriptions. All against `api.calendly.com`.
**Categories**: Scheduling & Events · Productivity · Calendar · Productivity · Meetings · **Auth**: OAuth 2.0, Personal Access Token · **Actions**: 11
## Authentication
### OAuth 2.0 Authentication
Authenticate using Calendly OAuth 2.0 flow
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Calendly App Client ID | Yes | `-` |
| Client Secret | Calendly App Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://auth.calendly.com/oauth/authorize`
- **Token URL**: `https://auth.calendly.com/oauth/token`
- **Scopes**: `default`
### Personal Access Token
Authenticate using a Calendly Personal Access Token
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Calendly Personal Access Token | Your Calendly Personal Access Token | Yes | `-` |
## Available Actions
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"resource": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Resource"
}
},
"required": [
"success"
],
"title": "GetCurrentUserOutput",
"type": "object"
}
```
### Parameters
User URI to filter events. Defaults to the authenticated user.
Organization URI to filter events
Filter by invitee email
Filter by event status ('active' or 'canceled')
Minimum start time (ISO 8601)
Maximum start time (ISO 8601)
Number of results to return (max 100) (Default: `20`)
Token for pagination
Sort order ('start_time:asc' or 'start_time:desc')
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"next_page_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page Token"
},
"next_page": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page"
},
"events": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Events",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListEventsOutput",
"type": "object"
}
```
### Parameters
The UUID of the event to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"resource": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Resource"
}
},
"required": [
"success"
],
"title": "GetEventOutput",
"type": "object"
}
```
### Parameters
The UUID of the event
Filter by invitee email
Filter by invitee status ('active' or 'canceled')
Number of results to return (max 100) (Default: `20`)
Token for pagination
Sort order ('created_at:asc' or 'created_at:desc')
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"next_page_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page Token"
},
"next_page": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page"
},
"invitees": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Invitees",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListEventInviteesOutput",
"type": "object"
}
```
### Parameters
User URI to filter event types
Organization URI to filter event types
Filter by active status
Number of results to return (max 100) (Default: `20`)
Token for pagination
Sort order ('name:asc' or 'name:desc')
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"next_page_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page Token"
},
"next_page": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page"
},
"event_types": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Event Types",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListEventTypesOutput",
"type": "object"
}
```
### Parameters
URI or UUID of the event type
Maximum events that can be scheduled with this link (Default: `1`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"booking_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Booking Url"
},
"owner": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Owner"
},
"owner_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Owner Type"
}
},
"required": [
"success"
],
"title": "CreateSchedulingLinkOutput",
"type": "object"
}
```
### Parameters
URI of the invitee to mark as no-show
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"resource": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Resource"
}
},
"required": [
"success"
],
"title": "CreateInviteeNoShowOutput",
"type": "object"
}
```
### Parameters
URI or UUID of the user
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"schedules": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Schedules",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListUserAvailabilitySchedulesOutput",
"type": "object"
}
```
### Parameters
Organization URI. Defaults to the authenticated user's organization.
Filter by user URI
Number of results to return (max 100) (Default: `20`)
Token for pagination
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"next_page_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page Token"
},
"next_page": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page"
},
"members": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Members",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListOrganizationMembersOutput",
"type": "object"
}
```
### Parameters
Organization URI to list groups for
Number of results to return (max 100) (Default: `20`)
Token for pagination
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"next_page_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page Token"
},
"next_page": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page"
},
"groups": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Groups",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListGroupsOutput",
"type": "object"
}
```
### Parameters
Organization URI
Scope ('organization' or 'user')
User URI (required if scope is 'user')
Number of results to return (max 100) (Default: `20`)
Token for pagination
Sort order ('created_at:asc' or 'created_at:desc')
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"next_page_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page Token"
},
"next_page": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page"
},
"webhooks": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Webhooks",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListWebhookSubscriptionsOutput",
"type": "object"
}
```
## Limits & Quotas
- Auto-resolves missing `user` / `organization` filters via a side
call to `/users/me` (same as legacy). This costs one extra request
per call but matches Calendly's expected pattern when the operator
doesn't pass a filter explicitly.
- Count parameters are clamped to 100 (Calendly's max page size).
- `owner` / `user` parameters accept either a bare UUID or a full
Calendly URI; bare UUIDs are promoted to the canonical
`https://api.calendly.com//` form.
- Failures (non-2xx, exceptions) surface as `success=False` + `error`.
## Related integrations
## Links
- [Calendly](https://calendly.com)
---
# Canva Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/canva
Design platform for creating visual content, presentations, and documents
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/canva/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Canva** to any ModuleX agent or workflow. Design platform integration for creating, listing, exporting, and importing visual content via the Canva Connect REST API (`api.canva.com/rest/v1`).
**Categories**: Productivity & Collaboration · Design & Creative Tools · **Auth**: OAuth2 · **Actions**: 5
## Authentication
### OAuth2 Authentication
Connect using Canva OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Canva Connect API OAuth App Client ID | Yes | `-` |
| Client Secret | Canva Connect API OAuth App Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://www.canva.com/api/oauth/authorize`
- **Token URL**: `https://api.canva.com/rest/v1/oauth/token`
- **Scopes**: `design:content:read`, `design:content:write`, `design:meta:read`, `asset:read`, `asset:write`
## Available Actions
### Parameters
The desired design type: 'preset' (provide design_type_name) or 'custom' (provide width and height)
The name of the design
The ID of the asset to add to the new design
The preset design type name: 'doc', 'whiteboard', or 'presentation'. Only applicable when design_type is 'preset'
Width in pixels (40-8000). Only applicable when design_type is 'custom'
Height in pixels (40-8000). Only applicable when design_type is 'custom'
### Response
```json
{
"$defs": {
"DesignSummary": {
"additionalProperties": false,
"description": "A design object returned by Canva.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"owner": {
"anyOf": [
{
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Owner"
},
"thumbnail": {
"anyOf": [
{
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
},
{
"type": "null"
}
]
},
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Thumbnail"
},
"urls": {
"anyOf": [
{
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Urls"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"title": "DesignSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"design": {
"anyOf": [
{
"$ref": "#/$defs/DesignSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateDesignOutput",
"type": "object"
}
```
### Parameters
The name for the imported design
URL of the file to import into Canva
### Response
```json
{
"$defs": {
"ImportJob": {
"additionalProperties": false,
"description": "A design import job status object.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"design_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Design Id"
}
},
"title": "ImportJob",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"job": {
"anyOf": [
{
"$ref": "#/$defs/ImportJob"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateDesignImportJobOutput",
"type": "object"
}
```
### Parameters
The ID of the design to export
Export format: 'pdf', 'jpg', 'png', 'pptx', 'gif', or 'mp4'
Array of page numbers (integers) to export. First page is 1. If omitted, all pages are exported
JPG quality 1-100. Only applicable for 'jpg' format
MP4 resolution: 'horizontal_480p', 'horizontal_720p', 'horizontal_1080p', 'horizontal_4k', 'vertical_480p', 'vertical_720p', 'vertical_1080p', 'vertical_4k'
PDF paper size: 'a4', 'a3', 'letter', or 'legal'
Use lossless compression for PNG exports
Merge multi-page designs into a single PNG image
Export quality tier: 'regular' or 'pro'. Pro may fail for premium elements
Export height in pixels. Applicable for jpg, png, gif formats
Export width in pixels. Applicable for jpg, png, gif formats
### Response
```json
{
"$defs": {
"ExportJob": {
"additionalProperties": false,
"description": "An export job status object.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"urls": {
"items": {
"type": "string"
},
"title": "Urls",
"type": "array"
}
},
"title": "ExportJob",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"job": {
"anyOf": [
{
"$ref": "#/$defs/ExportJob"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "ExportDesignOutput",
"type": "object"
}
```
### Parameters
Search keyword or phrase (max 255 characters)
Pagination cursor from a previous response to get the next page
Filter by ownership: 'any', 'owned', or 'shared' (Default: `any`)
Sort order: 'relevance', 'modified_descending', 'modified_ascending', 'title_descending', 'title_ascending' (Default: `relevance`)
Maximum designs to return per request (1-100) (Default: `25`)
### Response
```json
{
"$defs": {
"DesignSummary": {
"additionalProperties": false,
"description": "A design object returned by Canva.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"owner": {
"anyOf": [
{
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Owner"
},
"thumbnail": {
"anyOf": [
{
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
},
{
"type": "null"
}
]
},
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Thumbnail"
},
"urls": {
"anyOf": [
{
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Urls"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"title": "DesignSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"$ref": "#/$defs/DesignSummary"
},
"title": "Items",
"type": "array"
},
"continuation": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Continuation"
}
},
"required": [
"success"
],
"title": "ListDesignsOutput",
"type": "object"
}
```
### Parameters
The asset's name
URL of the file to upload as an asset to Canva
### Response
```json
{
"$defs": {
"UploadJob": {
"additionalProperties": false,
"description": "An asset upload job status object.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"asset": {
"anyOf": [
{
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Asset"
}
},
"title": "UploadJob",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"job": {
"anyOf": [
{
"$ref": "#/$defs/UploadJob"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UploadAssetOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limits**: Canva Connect API enforces per-app rate limits (varies by plan; typically 100 requests/minute for standard apps).
- **Export/Import jobs**: Asynchronous — the tool polls until completion (up to ~60 seconds). Large designs may take longer.
- **File uploads**: Maximum file size varies by asset type (images up to 25 MB, videos up to 1 GB).
- **Error model**: Non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Canva](https://www.canva.com)
---
# Clay Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/clay
Push records into a Clay table via its inbound webhook so Clay can run its data-enrichment waterfall on prospects and accounts.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/clay/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Clay** to any ModuleX agent or workflow. Push records into a [Clay](https://www.clay.com) table through that table's inbound webhook so Clay can run its data-enrichment waterfall on prospects and accounts.
**Categories**: Sales · CRM · Enrichment · **Auth**: Webhook Auth Token · **Actions**: 1
## Authentication
### Webhook Auth Token
Authenticate with the optional auth token from a Clay table's webhook source. Sent in the x-clay-webhook-auth header. Leave empty if the table's webhook does not require authentication.
In a Clay workbook, click + Add and search for 'Webhooks', then 'Monitor webhook'.
Copy the webhook URL Clay shows for the table — this is the webhook_url action parameter.
If the table has webhook authentication enabled, copy the auth token Clay displays (it is shown only once).
Paste the auth token below; otherwise leave it blank.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Clay Webhook Auth Token | Optional auth token for a Clay table webhook, sent in the x-clay-webhook-auth header | No | `-` |
## Available Actions
### Parameters
The Clay table webhook URL to send the record to
The record to populate, as a JSON object whose keys map to the Clay table column names (e.g. name, email, company, domain)
### Response
```json
{
"$defs": {
"PopulateMetadata": {
"additionalProperties": false,
"description": "Transport-level metadata about the webhook response.",
"properties": {
"status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"status_text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status Text"
},
"headers": {
"additionalProperties": {
"type": "string"
},
"title": "Headers",
"type": "object"
},
"timestamp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp"
},
"content_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Type"
}
},
"title": "PopulateMetadata",
"type": "object"
}
},
"additionalProperties": false,
"description": "Result of pushing a record to a Clay table webhook.",
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{},
{
"type": "null"
}
],
"default": null,
"title": "Data"
},
"metadata": {
"anyOf": [
{
"$ref": "#/$defs/PopulateMetadata"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "PopulateOutput",
"type": "object"
}
```
## Limits & Quotas
- **Asynchronous enrichment**: the webhook acknowledges receipt
immediately; Clay runs its enrichment waterfall afterward, so the
enriched columns appear inside Clay, not in the tool response.
- **Response shape**: the tool returns whatever the webhook
acknowledges (`data`) plus transport `metadata` (HTTP status, status
text, response headers, a call-time ISO-8601 UTC timestamp, and the
content type). A non-JSON acknowledgment is wrapped as
`{"message": ""}`.
- **Error model**: non-2xx responses, timeouts, and unexpected
exceptions are caught and returned as `success=False` + `error`
rather than raising.
## Related integrations
## Links
- [Clay](https://www.clay.com)
---
# ClickUp Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/clickup
ClickUp integration: workspaces, spaces, folders, lists, tasks, comments, tags, and team members.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/clickup/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **ClickUp** to any ModuleX agent or workflow. ClickUp project management integration via the v2 REST API. Pure HTTP. 23 actions across workspaces, spaces, folders, lists, tasks, comments, tags, and team members.
**Categories**: Project & Task Management · Project Management · Productivity · Communication & Collaboration · **Auth**: API Key · **Actions**: 23
## Authentication
### API Key Authentication
Authenticate using your ClickUp Personal API Token
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| ClickUp API Key | Your ClickUp Personal API Token from Settings > Apps | Yes | `pk_xxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"teams": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Teams",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetTeamsOutput",
"type": "object"
}
```
### Parameters
Team (workspace) ID
Include archived spaces (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"spaces": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Spaces",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"team_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Team Id"
}
},
"required": [
"success"
],
"title": "GetSpacesOutput",
"type": "object"
}
```
### Parameters
Space ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "GetSpaceOutput",
"type": "object"
}
```
### Parameters
Team (workspace) ID
Space name
Allow multiple assignees (Default: `true`)
Optional features (due_dates, time_tracking, …)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "CreateSpaceOutput",
"type": "object"
}
```
### Parameters
Space ID
Include archived folders (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"folders": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Folders",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"space_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Space Id"
}
},
"required": [
"success"
],
"title": "GetFoldersOutput",
"type": "object"
}
```
### Parameters
Folder ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "GetFolderOutput",
"type": "object"
}
```
### Parameters
Space ID
Folder name
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "CreateFolderOutput",
"type": "object"
}
```
### Parameters
Folder ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"deleted": {
"default": false,
"title": "Deleted",
"type": "boolean"
},
"folder_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Folder Id"
}
},
"required": [
"success"
],
"title": "DeleteFolderOutput",
"type": "object"
}
```
### Parameters
Folder ID
Space ID
Include archived (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"lists": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Lists",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"folder_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Folder Id"
},
"space_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Space Id"
}
},
"required": [
"success"
],
"title": "GetListsOutput",
"type": "object"
}
```
### Parameters
List ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "GetListOutput",
"type": "object"
}
```
### Parameters
List name
Folder ID
Space ID
List description
Due date (epoch ms)
Priority (1=Urgent..4=Low)
Assignee user ID
List status
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "CreateListOutput",
"type": "object"
}
```
### Parameters
List ID
Whether to archive (Default: `false`)
Include closed tasks (Default: `false`)
Include subtasks (Default: `false`)
Page number (0-indexed) (Default: `0`)
id / created / updated / due_date
Reverse sort order (Default: `false`)
Filter by status names
Filter by assignee IDs
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"tasks": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Tasks",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"list_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "List Id"
}
},
"required": [
"success"
],
"title": "GetTasksOutput",
"type": "object"
}
```
### Parameters
Task ID
If true, task_id is a custom task ID (e.g. 'ABC-123') (Default: `false`)
Required when custom_task_ids=true
Include subtasks in response (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "GetTaskOutput",
"type": "object"
}
```
### Parameters
List ID
Task name
Markdown description
Status name
1=Urgent..4=Low
Due date (epoch ms)
Whether due_date includes time (Default: `false`)
Start date (epoch ms)
Whether start_date includes time (Default: `false`)
Assignee user IDs
Tag names
Parent task ID (for subtasks)
Notify all assignees (Default: `true`)
Time estimate (ms)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "CreateTaskOutput",
"type": "object"
}
```
### Parameters
Task ID
If true, task_id is a custom task ID (e.g. 'ABC-123') (Default: `false`)
Required when custom_task_ids=true
Updated task name
Updated task description
Updated status
Updated priority (1=Urgent..4=Low)
Updated due date (epoch ms)
Whether due_date includes time
Updated start date (epoch ms)
Whether start_date includes time
User IDs to add
User IDs to remove
Whether to archive
Time estimate (ms)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "UpdateTaskOutput",
"type": "object"
}
```
### Parameters
Task ID
If true, task_id is a custom task ID (e.g. 'ABC-123') (Default: `false`)
Required when custom_task_ids=true
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"deleted": {
"default": false,
"title": "Deleted",
"type": "boolean"
},
"task_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Task Id"
}
},
"required": [
"success"
],
"title": "DeleteTaskOutput",
"type": "object"
}
```
### Parameters
Task ID
If true, task_id is a custom task ID (e.g. 'ABC-123') (Default: `false`)
Required when custom_task_ids=true
Pagination start position
Comment ID to start from
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"comments": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Comments",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"task_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Task Id"
}
},
"required": [
"success"
],
"title": "GetTaskCommentsOutput",
"type": "object"
}
```
### Parameters
Task ID
If true, task_id is a custom task ID (e.g. 'ABC-123') (Default: `false`)
Required when custom_task_ids=true
Comment body
Notify all assignees (Default: `false`)
Assigned user ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "CreateTaskCommentOutput",
"type": "object"
}
```
### Parameters
Team (workspace) ID
Search query
Status filter
Assignee user IDs
Tag names
List IDs
Folder IDs
Space IDs
Include closed tasks (Default: `false`)
Page number (0-indexed) (Default: `0`)
Order field
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"tasks": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Tasks",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"team_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Team Id"
}
},
"required": [
"success"
],
"title": "SearchTasksOutput",
"type": "object"
}
```
### Parameters
Space ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"tags": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Tags",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"space_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Space Id"
}
},
"required": [
"success"
],
"title": "GetSpaceTagsOutput",
"type": "object"
}
```
### Parameters
Task ID
Tag name
If true, task_id is a custom task ID (e.g. 'ABC-123') (Default: `false`)
Required when custom_task_ids=true
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"added": {
"default": false,
"title": "Added",
"type": "boolean"
},
"task_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Task Id"
},
"tag_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Tag Name"
}
},
"required": [
"success"
],
"title": "AddTagToTaskOutput",
"type": "object"
}
```
### Parameters
Task ID
Tag name
If true, task_id is a custom task ID (e.g. 'ABC-123') (Default: `false`)
Required when custom_task_ids=true
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"removed": {
"default": false,
"title": "Removed",
"type": "boolean"
},
"task_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Task Id"
},
"tag_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Tag Name"
}
},
"required": [
"success"
],
"title": "RemoveTagFromTaskOutput",
"type": "object"
}
```
### Parameters
Team (workspace) ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"members": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Members",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"team_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Team Id"
}
},
"required": [
"success"
],
"title": "GetTeamMembersOutput",
"type": "object"
}
```
## Related integrations
## Links
- [ClickUp](https://clickup.com)
---
# Cloudflare Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/cloudflare
Cloudflare DNS, WAF, zones, firewall rules, and load balancer management.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/cloudflare/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Cloudflare** to any ModuleX agent or workflow. Cloudflare v4 API integration: DNS, WAF lists, zones, firewall rules, load balancer monitors & pools, account discovery. All against `api.cloudflare.com/client/v4`.
**Categories**: Developer Tools & Infrastructure · Security · Infrastructure · Networking · **Auth**: API Token · **Actions**: 13
## Authentication
### API Token Authentication
Authenticate using your Cloudflare API Token (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Cloudflare API Token | Your Cloudflare API Token for authentication | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
Zone name filter
Zone status: active, pending, initializing, moved, deleted, deactivated
Account identifier filter
Page number (Default: `1`)
Results per page (max 50 for most endpoints) (Default: `20`)
Sort order: name, status, account.id, account.name
Sort direction (asc/desc) (Default: `asc`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Page"
},
"per_page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Per Page"
}
},
"required": [
"success"
],
"title": "ListZonesOutput",
"type": "object"
}
```
### Parameters
Zone identifier
DNS record type (A, AAAA, CNAME, TXT, MX, NS, SRV, etc.)
DNS record name
DNS record content
TTL (1 = automatic) (Default: `1`)
Priority for MX/SRV records
Proxy through Cloudflare (Default: `false`)
DNS record comment
DNS record tags
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Page"
},
"per_page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Per Page"
}
},
"required": [
"success"
],
"title": "CreateDNSRecordOutput",
"type": "object"
}
```
### Parameters
Zone identifier
DNS record identifier
DNS record type
DNS record name
DNS record content
TTL
Priority for MX/SRV records
Proxy through Cloudflare
DNS record comment
DNS record tags
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Page"
},
"per_page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Per Page"
}
},
"required": [
"success"
],
"title": "UpdateDNSRecordOutput",
"type": "object"
}
```
### Parameters
Zone identifier
DNS record identifier to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Page"
},
"per_page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Per Page"
}
},
"required": [
"success"
],
"title": "DeleteDNSRecordOutput",
"type": "object"
}
```
### Parameters
Account identifier
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Page"
},
"per_page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Per Page"
}
},
"required": [
"success"
],
"title": "ListWAFListsOutput",
"type": "object"
}
```
### Parameters
Account identifier
Name of the list
List type: ip, redirect, hostname, asn
Description of the list
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Page"
},
"per_page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Per Page"
}
},
"required": [
"success"
],
"title": "CreateWAFListOutput",
"type": "object"
}
```
### Parameters
Account identifier
List identifier
New description for the list
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Page"
},
"per_page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Per Page"
}
},
"required": [
"success"
],
"title": "UpdateWAFListOutput",
"type": "object"
}
```
### Parameters
Account identifier
List identifier to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Page"
},
"per_page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Per Page"
}
},
"required": [
"success"
],
"title": "DeleteWAFListOutput",
"type": "object"
}
```
### Parameters
Page number (Default: `1`)
Results per page (max 50 for most endpoints) (Default: `20`)
Sort direction (asc/desc) (Default: `asc`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Page"
},
"per_page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Per Page"
}
},
"required": [
"success"
],
"title": "ListAccountsOutput",
"type": "object"
}
```
### Parameters
Account identifier
Page number (Default: `1`)
Results per page (max 50 for most endpoints) (Default: `20`)
Sort: user.first_name, user.last_name, user.email, status (Default: `status`)
Sort direction (asc/desc) (Default: `asc`)
Filter by status: accepted, pending, rejected
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Page"
},
"per_page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Per Page"
}
},
"required": [
"success"
],
"title": "ListAccountMembersOutput",
"type": "object"
}
```
### Parameters
Zone identifier
Page number (Default: `1`)
Results per page (max 50 for most endpoints) (Default: `25`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Page"
},
"per_page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Per Page"
}
},
"required": [
"success"
],
"title": "ListFirewallRulesOutput",
"type": "object"
}
```
### Parameters
Account identifier
Page number (Default: `1`)
Results per page (max 50 for most endpoints) (Default: `25`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Page"
},
"per_page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Per Page"
}
},
"required": [
"success"
],
"title": "ListMonitorsOutput",
"type": "object"
}
```
### Parameters
Account identifier
Page number (Default: `1`)
Results per page (max 50 for most endpoints) (Default: `25`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Page"
},
"per_page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Per Page"
}
},
"required": [
"success"
],
"title": "ListPoolsOutput",
"type": "object"
}
```
## Limits & Quotas
- Cloudflare wraps every response in
`{"success", "errors", "messages", "result", "result_info"}`. The
shared `_call` helper checks the envelope's `success` flag (not just
HTTP status), pulls `errors[0].message` on failure, and lifts
`result_info` pagination (`total_count`, `page`, `per_page`) onto
the output's top-level `total`/`page`/`per_page` fields for list
actions.
- Most list endpoints cap `per_page` at 50; firewall rules cap at 100.
- `result` is open: list endpoints return a JSON array; CRUD
endpoints return the object directly. Mirrors the upstream shape.
## Related integrations
## Links
- [Cloudflare](https://cloudflare.com)
---
# Coinbase Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/coinbase
Cryptocurrency trading and wallet management platform for buying, selling, and storing digital assets via the Coinbase Developer Platform (CDP) API.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/coinbase/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Coinbase** to any ModuleX agent or workflow. Cryptocurrency trading and wallet management via the **Coinbase Developer Platform (CDP) API** (v2 + v3 brokerage). Pure HTTP; the only runtime dependency added is `cryptography` for local JWT signing.
**Categories**: Finance & Payments · Business Services · Finance · Trading · Market · **Auth**: CDP API Key + Secret · **Actions**: 8
## Authentication
### CDP API Key + Secret
Authenticate using a Coinbase Developer Platform API key pair: the key ID and either an ECDSA (PEM) or Ed25519 (base64) private key. JWT signing happens locally.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| API Key ID | Your Coinbase CDP API Key ID (e.g. organizations/{org_id}/apiKeys/{key_id}) | Yes | `organizations/{org_id}/apiKeys/{key_id}` |
| API Secret | Coinbase CDP API Secret (PEM for ECDSA or base64 for Ed25519). Used to sign JWTs locally. | Yes | `-` |
## Available Actions
### Parameters
Maximum accounts to return (1-100) (Default: `25`)
### Response
```json
{
"$defs": {
"AccountRow": {
"additionalProperties": false,
"properties": {
"uuid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uuid"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"currency": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Currency"
},
"available_balance": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Available Balance"
},
"available_balance_currency": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Available Balance Currency"
},
"hold_balance": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hold Balance"
},
"hold_balance_currency": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hold Balance Currency"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"active": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Active"
},
"ready": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Ready"
},
"default": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Default"
}
},
"title": "AccountRow",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"accounts": {
"items": {
"$ref": "#/$defs/AccountRow"
},
"title": "Accounts",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
},
"has_next": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has Next"
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cursor"
}
},
"required": [
"success"
],
"title": "GetAccountsOutput",
"type": "object"
}
```
### Parameters
The ID of the account
### Response
```json
{
"$defs": {
"AccountRow": {
"additionalProperties": false,
"properties": {
"uuid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uuid"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"currency": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Currency"
},
"available_balance": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Available Balance"
},
"available_balance_currency": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Available Balance Currency"
},
"hold_balance": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hold Balance"
},
"hold_balance_currency": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hold Balance Currency"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"active": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Active"
},
"ready": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Ready"
},
"default": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Default"
}
},
"title": "AccountRow",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"account": {
"anyOf": [
{
"$ref": "#/$defs/AccountRow"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetAccountOutput",
"type": "object"
}
```
### Parameters
The ID of the account
Maximum transactions to return (1-100) (Default: `25`)
Pagination cursor (last transaction ID)
### Response
```json
{
"$defs": {
"TransactionRow": {
"additionalProperties": false,
"properties": {
"entry_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Entry Id"
},
"trade_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Trade Id"
},
"order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Order Id"
},
"trade_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Trade Time"
},
"trade_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Trade Type"
},
"price": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Price"
},
"size": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"commission": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Commission"
},
"product_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Product Id"
},
"sequence_timestamp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sequence Timestamp"
},
"liquidity_indicator": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Liquidity Indicator"
},
"size_in_quote": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Size In Quote"
},
"user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User Id"
},
"side": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Side"
}
},
"title": "TransactionRow",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"transactions": {
"items": {
"$ref": "#/$defs/TransactionRow"
},
"title": "Transactions",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cursor"
}
},
"required": [
"success"
],
"title": "GetTransactionsOutput",
"type": "object"
}
```
### Parameters
The ID of the account
The amount
The currency code (e.g. 'BTC', 'ETH', 'USD')
Optional payment method ID
### Response
```json
{
"$defs": {
"_OrderInfo": {
"additionalProperties": false,
"properties": {
"order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Order Id"
},
"product_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Product Id"
},
"side": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Side"
},
"client_order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Client Order Id"
}
},
"title": "_OrderInfo",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"order": {
"anyOf": [
{
"$ref": "#/$defs/_OrderInfo"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "PlaceBuyOrderOutput",
"type": "object"
}
```
### Parameters
The ID of the account
The amount
The currency code (e.g. 'BTC', 'ETH', 'USD')
Destination address (or payment method ID)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"amount": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Amount"
},
"asset": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Asset"
},
"fee": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Fee"
},
"transaction_hash": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Transaction Hash"
},
"destination_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Destination Address"
},
"network": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Network"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
}
},
"required": [
"success"
],
"title": "WithdrawFundsOutput",
"type": "object"
}
```
### Parameters
Base currency for the rate table (Default: `USD`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"currency": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Currency"
},
"rates": {
"additionalProperties": true,
"title": "Rates",
"type": "object"
}
},
"required": [
"success"
],
"title": "GetExchangeRatesOutput",
"type": "object"
}
```
### Parameters
Currency pair (e.g. 'BTC-USD')
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"base": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Base"
},
"currency": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Currency"
},
"amount": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Amount"
}
},
"required": [
"success"
],
"title": "GetSpotPriceOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"PaymentMethodRow": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"currency": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Currency"
},
"allow_buy": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Allow Buy"
},
"allow_sell": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Allow Sell"
},
"allow_deposit": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Allow Deposit"
},
"allow_withdraw": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Allow Withdraw"
},
"verified": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Verified"
}
},
"title": "PaymentMethodRow",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"payment_methods": {
"items": {
"$ref": "#/$defs/PaymentMethodRow"
},
"title": "Payment Methods",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetPaymentMethodsOutput",
"type": "object"
}
```
## Related integrations
## Links
- [Coinbase](https://www.coinbase.com)
---
# CoinMarketCap Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/coinmarketcap
Cryptocurrency market data, quotes, and metadata from the CoinMarketCap API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/coinmarketcap/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **CoinMarketCap** to any ModuleX agent or workflow. Cryptocurrency market data, quotes, and metadata from the CoinMarketCap REST API (`pro-api.coinmarketcap.com`).
**Categories**: Finance & Payments · Finance · Cryptocurrency · Market Data · **Auth**: API Key · **Actions**: 4
## Authentication
### API Key Authentication
Authenticate using your CoinMarketCap API key
Go to https://coinmarketcap.com/api/ and sign up for an account
Navigate to your API dashboard
Copy your API key
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| CoinMarketCap API Key | Your CoinMarketCap API key from the developer dashboard | Yes | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
## Available Actions
### Parameters
One or more comma-separated CoinMarketCap cryptocurrency IDs. Example: 1,2,1027
When true, invalid lookups will be skipped allowing valid cryptocurrencies to still be returned (Default: `false`)
Comma-separated supplemental data fields to return. Valid values: urls, logo, description, tags, platform, date_added, notice, status
### Response
```json
{
"$defs": {
"CryptocurrencyMetadata": {
"additionalProperties": false,
"description": "Metadata for a single cryptocurrency.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"symbol": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Symbol"
},
"slug": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Slug"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"logo": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Logo"
},
"date_added": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Date Added"
},
"category": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Category"
}
},
"title": "CryptocurrencyMetadata",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"additionalProperties": {
"$ref": "#/$defs/CryptocurrencyMetadata"
},
"title": "Data",
"type": "object"
}
},
"required": [
"success"
],
"title": "GetCryptocurrencyMetadataOutput",
"type": "object"
}
```
### Parameters
Filter by status. Valid values: active, inactive, untracked. Comma-separated for multiple.
Offset the start (1-based index) of the paginated list of items to return
Number of results to return. Default 100 (Default: `100`)
Sort field. Valid values: cmc_rank, id
Comma-separated list of cryptocurrency symbols to return IDs for. If passed, other options are ignored.
Comma-separated supplemental data fields. Valid values: platform, first_historical_data, last_historical_data, is_active, status
### Response
```json
{
"$defs": {
"CryptocurrencyMapItem": {
"additionalProperties": false,
"description": "A cryptocurrency mapping entry.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"symbol": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Symbol"
},
"slug": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Slug"
},
"is_active": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Active"
},
"first_historical_data": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Historical Data"
},
"last_historical_data": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Historical Data"
}
},
"title": "CryptocurrencyMapItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"items": {
"$ref": "#/$defs/CryptocurrencyMapItem"
},
"title": "Data",
"type": "array"
}
},
"required": [
"success"
],
"title": "IdMapOutput",
"type": "object"
}
```
### Parameters
Offset the start (1-based index) of the paginated list of items to return
Number of results to return
Minimum 24 hour USD volume to filter results by
Comma-separated list of cryptocurrency or fiat currency symbols to calculate market quotes in
Comma-separated CoinMarketCap IDs to calculate market quotes in. Cannot be used with convert.
Sort field. Valid values: market_cap, name, symbol, date_added, price, circulating_supply, total_supply, max_supply, num_market_pairs, volume_24h, percent_change_1h, percent_change_24h, percent_change_7d
Sort direction. Valid values: asc, desc
Type of cryptocurrency to include. Valid values: all, coins, tokens
Comma-separated supplemental data fields. Valid values: num_market_pairs, cmc_rank, date_added, tags, platform, max_supply, circulating_supply, total_supply
### Response
```json
{
"$defs": {
"ListingItem": {
"additionalProperties": false,
"description": "A cryptocurrency listing entry with market data.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"symbol": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Symbol"
},
"slug": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Slug"
},
"cmc_rank": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Cmc Rank"
},
"circulating_supply": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Circulating Supply"
},
"total_supply": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Supply"
},
"max_supply": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Max Supply"
},
"quote": {
"additionalProperties": {
"$ref": "#/$defs/QuoteData"
},
"title": "Quote",
"type": "object"
}
},
"title": "ListingItem",
"type": "object"
},
"QuoteData": {
"additionalProperties": false,
"description": "Quote data for a single currency conversion.",
"properties": {
"price": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Price"
},
"volume_24h": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Volume 24H"
},
"market_cap": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Market Cap"
},
"percent_change_1h": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Percent Change 1H"
},
"percent_change_24h": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Percent Change 24H"
},
"percent_change_7d": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Percent Change 7D"
},
"last_updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Updated"
}
},
"title": "QuoteData",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"items": {
"$ref": "#/$defs/ListingItem"
},
"title": "Data",
"type": "array"
}
},
"required": [
"success"
],
"title": "LatestListingsOutput",
"type": "object"
}
```
### Parameters
One or more comma-separated CoinMarketCap cryptocurrency IDs. Example: 1,2
Comma-separated list of cryptocurrency slugs. Example: bitcoin,ethereum
Comma-separated cryptocurrency symbols. Example: BTC,ETH
Comma-separated list of currency symbols to calculate quotes in
Comma-separated CoinMarketCap IDs to calculate quotes in. Cannot be used with convert.
### Response
```json
{
"$defs": {
"CryptocurrencyQuote": {
"additionalProperties": false,
"description": "Quote data for a specific cryptocurrency.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"symbol": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Symbol"
},
"slug": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Slug"
},
"cmc_rank": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Cmc Rank"
},
"quote": {
"additionalProperties": {
"$ref": "#/$defs/QuoteData"
},
"title": "Quote",
"type": "object"
}
},
"title": "CryptocurrencyQuote",
"type": "object"
},
"QuoteData": {
"additionalProperties": false,
"description": "Quote data for a single currency conversion.",
"properties": {
"price": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Price"
},
"volume_24h": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Volume 24H"
},
"market_cap": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Market Cap"
},
"percent_change_1h": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Percent Change 1H"
},
"percent_change_24h": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Percent Change 24H"
},
"percent_change_7d": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Percent Change 7D"
},
"last_updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Updated"
}
},
"title": "QuoteData",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"additionalProperties": {
"$ref": "#/$defs/CryptocurrencyQuote"
},
"title": "Data",
"type": "object"
}
},
"required": [
"success"
],
"title": "LatestQuotesOutput",
"type": "object"
}
```
## Limits & Quotas
- **Basic (free) plan**: 333 calls/day, 10,000 calls/month.
- **Hobbyist plan**: 10,000 calls/month.
- **Standard plan and above**: higher limits per the pricing page.
- Rate limiting is applied per API key. Exceeding limits returns HTTP 429.
- **Error model**: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [CoinMarketCap](https://coinmarketcap.com)
---
# ConvertAPI Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/convertapi
Powerful file conversion service supporting hundreds of format conversions including documents, images, spreadsheets, and web pages to PDF/JPG.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/convertapi/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **ConvertAPI** to any ModuleX agent or workflow. File-format conversion (PDF, DOCX, JPG, etc.), base64 file conversion, web-page-to-PDF rendering, and format-discovery against the ConvertAPI v2 REST endpoints (`v2.convertapi.com`).
**Categories**: Productivity & Collaboration · Utilities · Convert · Documents · **Auth**: API Key · **Actions**: 4
## Authentication
### API Key Authentication
Authenticate using your ConvertAPI Secret key
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| ConvertAPI Secret | Your ConvertAPI Secret key for authentication | Yes | `xxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
URL of the file to convert
Input file format (e.g. 'docx', 'pdf', 'png')
Output file format (e.g. 'pdf', 'jpg', 'docx')
Output filename without extension
Conversion timeout in seconds (Default: `300`)
### Response
```json
{
"$defs": {
"ConvertedFile": {
"additionalProperties": false,
"properties": {
"filename": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Filename"
},
"file_size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "File Size"
},
"file_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "File Url"
},
"file_data_base64": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "File Data Base64"
}
},
"title": "ConvertedFile",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"conversion_cost": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Conversion Cost"
},
"files": {
"items": {
"$ref": "#/$defs/ConvertedFile"
},
"title": "Files",
"type": "array"
},
"format_from": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Format From"
},
"format_to": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Format To"
}
},
"required": [
"success"
],
"title": "ConvertFileOutput",
"type": "object"
}
```
### Parameters
Base64-encoded file content
Input file format (e.g. 'docx', 'pdf')
Output file format (e.g. 'pdf', 'jpg')
Output filename without extension (Default: `converted`)
Conversion timeout in seconds (Default: `300`)
### Response
```json
{
"$defs": {
"ConvertedFile": {
"additionalProperties": false,
"properties": {
"filename": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Filename"
},
"file_size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "File Size"
},
"file_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "File Url"
},
"file_data_base64": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "File Data Base64"
}
},
"title": "ConvertedFile",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"conversion_cost": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Conversion Cost"
},
"files": {
"items": {
"$ref": "#/$defs/ConvertedFile"
},
"title": "Files",
"type": "array"
},
"format_from": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Format From"
},
"format_to": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Format To"
}
},
"required": [
"success"
],
"title": "ConvertBase64FileOutput",
"type": "object"
}
```
### Parameters
Website URL to convert
Output format: 'pdf' or 'jpg' (Default: `pdf`)
Output filename without extension
Conversion timeout in seconds (Default: `300`)
Delay in seconds to let page fully load before conversion
PDF page orientation ('portrait' or 'landscape')
PDF page size (e.g. 'a4', 'letter', 'legal')
Allow web pages to run JavaScript (Default: `true`)
Block ads in the converting page (Default: `false`)
Try to remove cookie consent popups (Default: `false`)
### Response
```json
{
"$defs": {
"ConvertedFile": {
"additionalProperties": false,
"properties": {
"filename": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Filename"
},
"file_size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "File Size"
},
"file_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "File Url"
},
"file_data_base64": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "File Data Base64"
}
},
"title": "ConvertedFile",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"conversion_cost": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Conversion Cost"
},
"files": {
"items": {
"$ref": "#/$defs/ConvertedFile"
},
"title": "Files",
"type": "array"
},
"source_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Source Url"
},
"format_to": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Format To"
}
},
"required": [
"success"
],
"title": "ConvertWebUrlOutput",
"type": "object"
}
```
### Parameters
Input format to check (e.g. 'docx', 'pdf', 'png')
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"format_from": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Format From"
},
"supported_formats": {
"items": {
"type": "string"
},
"title": "Supported Formats",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetSupportedFormatsOutput",
"type": "object"
}
```
## Limits & Quotas
- Conversions cost credits; `get_supported_formats` is free.
- Long-running conversions accept a per-call `timeout` (default 300s).
- Failures (non-200, empty `Files`, exceptions) surface as
`success=False` with `error`.
## Related integrations
## Links
- [ConvertAPI](https://www.convertapi.com)
---
# CrowdStrike Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/crowdstrike
Integrate CrowdStrike Identity Protection into workflows to search sensors, fetch sensor details by device ID, and run sensor aggregate queries against the Falcon API.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/crowdstrike/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **CrowdStrike** to any ModuleX agent or workflow. Query CrowdStrike Identity Protection sensors and aggregates through the Falcon API (`api.crowdstrike.com` and region-specific hosts). Search the sensor fleet with Falcon Query Language, pull detailed records by device ID, and run documented aggregate queries.
**Categories**: Monitoring & Observability · Security · Identity · **Auth**: API Key · **Actions**: 3
## Authentication
### API Key Authentication
Authenticate using a CrowdStrike Falcon API client. The client secret is the credential; the client ID and cloud region are supplied per action.
Sign in to the Falcon console and open Support and resources > API clients and keys.
Create an API client granting it the Identity Protection scopes (Identity Protection Entities: Read, Identity Protection Sensor: Read).
Copy the generated Client ID and Client Secret.
Paste the Client Secret below as the API key; provide the Client ID and your cloud region (us-1, us-2, eu-1, us-gov-1, us-gov-2) as action parameters.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| CrowdStrike Client Secret | Your CrowdStrike Falcon API client secret | Yes | `-` |
## Available Actions
### Parameters
CrowdStrike Falcon API client ID
CrowdStrike Falcon cloud region: one of 'us-1', 'us-2', 'eu-1', 'us-gov-1', 'us-gov-2' (Default: `us-1`)
Falcon Query Language (FQL) filter for sensor search
Maximum number of sensor records to return (1-200)
Pagination offset for the sensor query
Sort expression, e.g. 'status.asc'
### Response
```json
{
"$defs": {
"Pagination": {
"additionalProperties": false,
"description": "Pagination metadata echoed by the Falcon API (``meta.pagination``).",
"properties": {
"limit": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Limit"
},
"offset": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Offset"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
}
},
"title": "Pagination",
"type": "object"
},
"Sensor": {
"additionalProperties": false,
"description": "A single Identity Protection sensor/device record.\n\nThe Falcon API returns a rich device object; the most commonly used\nattributes are surfaced as typed fields and the complete upstream\nrecord is preserved verbatim in ``raw`` so nothing is lost. Field\nnames mirror the documented camelCase shape; values are read\npermissively with ``.get()`` (both snake_case and camelCase keys are\nattempted at parse time).",
"properties": {
"agent_version": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Agent Version"
},
"cid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cid"
},
"device_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Device Id"
},
"heartbeat_time": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Heartbeat Time"
},
"hostname": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hostname"
},
"idp_policy_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Idp Policy Id"
},
"idp_policy_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Idp Policy Name"
},
"ip_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ip Address"
},
"kerberos_config": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kerberos Config"
},
"ldap_config": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ldap Config"
},
"ldaps_config": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ldaps Config"
},
"machine_domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Machine Domain"
},
"ntlm_config": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ntlm Config"
},
"os_version": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Os Version"
},
"rdp_to_dc_config": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rdp To Dc Config"
},
"smb_to_dc_config": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Smb To Dc Config"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"status_causes": {
"items": {
"type": "string"
},
"title": "Status Causes",
"type": "array"
},
"ti_enabled": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ti Enabled"
},
"raw": {
"additionalProperties": true,
"title": "Raw",
"type": "object"
}
},
"title": "Sensor",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"sensors": {
"items": {
"$ref": "#/$defs/Sensor"
},
"title": "Sensors",
"type": "array"
},
"device_ids": {
"items": {
"type": "string"
},
"title": "Device Ids",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"pagination": {
"anyOf": [
{
"$ref": "#/$defs/Pagination"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "QuerySensorsOutput",
"type": "object"
}
```
### Parameters
CrowdStrike Falcon API client ID
CrowdStrike Falcon cloud region: one of 'us-1', 'us-2', 'eu-1', 'us-gov-1', 'us-gov-2' (Default: `us-1`)
List of CrowdStrike sensor device IDs (max 5000)
### Response
```json
{
"$defs": {
"Pagination": {
"additionalProperties": false,
"description": "Pagination metadata echoed by the Falcon API (``meta.pagination``).",
"properties": {
"limit": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Limit"
},
"offset": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Offset"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
}
},
"title": "Pagination",
"type": "object"
},
"Sensor": {
"additionalProperties": false,
"description": "A single Identity Protection sensor/device record.\n\nThe Falcon API returns a rich device object; the most commonly used\nattributes are surfaced as typed fields and the complete upstream\nrecord is preserved verbatim in ``raw`` so nothing is lost. Field\nnames mirror the documented camelCase shape; values are read\npermissively with ``.get()`` (both snake_case and camelCase keys are\nattempted at parse time).",
"properties": {
"agent_version": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Agent Version"
},
"cid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cid"
},
"device_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Device Id"
},
"heartbeat_time": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Heartbeat Time"
},
"hostname": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hostname"
},
"idp_policy_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Idp Policy Id"
},
"idp_policy_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Idp Policy Name"
},
"ip_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ip Address"
},
"kerberos_config": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kerberos Config"
},
"ldap_config": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ldap Config"
},
"ldaps_config": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ldaps Config"
},
"machine_domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Machine Domain"
},
"ntlm_config": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ntlm Config"
},
"os_version": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Os Version"
},
"rdp_to_dc_config": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rdp To Dc Config"
},
"smb_to_dc_config": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Smb To Dc Config"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"status_causes": {
"items": {
"type": "string"
},
"title": "Status Causes",
"type": "array"
},
"ti_enabled": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ti Enabled"
},
"raw": {
"additionalProperties": true,
"title": "Raw",
"type": "object"
}
},
"title": "Sensor",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"sensors": {
"items": {
"$ref": "#/$defs/Sensor"
},
"title": "Sensors",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"pagination": {
"anyOf": [
{
"$ref": "#/$defs/Pagination"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetSensorDetailsOutput",
"type": "object"
}
```
### Parameters
CrowdStrike Falcon API client ID
CrowdStrike Falcon cloud region: one of 'us-1', 'us-2', 'eu-1', 'us-gov-1', 'us-gov-2' (Default: `us-1`)
Aggregate query body documented by CrowdStrike (fields such as field, filter, name, size, sort, type, date_ranges, ranges, extended_bounds, sub_aggregates)
### Response
```json
{
"$defs": {
"AggregateBucket": {
"additionalProperties": false,
"description": "A single bucket within an aggregate result group.",
"properties": {
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"from_": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "From"
},
"key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Key"
},
"key_as_string": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Key As String"
},
"label": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Label"
},
"string_from": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "String From"
},
"string_to": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "String To"
},
"sub_aggregates": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Sub Aggregates",
"type": "array"
},
"to": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "To"
},
"value": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
},
"value_as_string": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Value As String"
}
},
"title": "AggregateBucket",
"type": "object"
},
"AggregateResult": {
"additionalProperties": false,
"description": "One aggregate result group returned by the aggregates endpoint.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"buckets": {
"items": {
"$ref": "#/$defs/AggregateBucket"
},
"title": "Buckets",
"type": "array"
},
"doc_count_error_upper_bound": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Doc Count Error Upper Bound"
},
"sum_other_doc_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Sum Other Doc Count"
}
},
"title": "AggregateResult",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"aggregates": {
"items": {
"$ref": "#/$defs/AggregateResult"
},
"title": "Aggregates",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetSensorAggregatesOutput",
"type": "object"
}
```
## Limits & Quotas
- **Token lifetime**: Falcon OAuth2 access tokens expire after ~30
minutes; each action requests a fresh token, so no token caching is
required.
- **Cloud region**: pick the host that matches your Falcon tenant
(`us-1` → `api.crowdstrike.com`, `us-2` → `api.us-2.crowdstrike.com`,
`eu-1` → `api.eu-1.crowdstrike.com`, GovCloud variants for
`us-gov-1`/`us-gov-2`).
- **`get_sensor_details`** accepts up to 5000 device IDs per call.
- **Error model**: non-2xx responses (including auth failures) and
timeouts are caught and returned as `success=False` + `error` rather
than raising. Plan for retries on the agent side based on the error
string.
## Related integrations
## Links
- [CrowdStrike](https://www.crowdstrike.com)
---
# Crunchbase Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/crunchbase
Access Crunchbase company and organization data for business intelligence and research
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/crunchbase/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Crunchbase** to any ModuleX agent or workflow. Access Crunchbase company and organization data for business intelligence and research via the Crunchbase REST API (`api.crunchbase.com/v4/data`).
**Categories**: Sales · Business Intelligence · Data · Research · **Auth**: API Key · **Actions**: 2
## Authentication
### API Key Authentication
Authenticate using your Crunchbase user key
Go to https://data.crunchbase.com and sign in
Navigate to your account settings or API key management
Copy your user key
Paste the key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Crunchbase User Key | Your Crunchbase API user key from data.crunchbase.com | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
UUID or permalink of the organization to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetOrganizationOutput",
"type": "object"
}
```
### Parameters
Fields to include on the resulting entity (e.g. identifier, short_description, name, website_url)
Array of query predicate objects for filtering organizations. Each object should have operator_id, type, values, and field_id keys.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"entities": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Entities",
"type": "array"
},
"total_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Count"
}
},
"required": [
"success"
],
"title": "SearchOrganizationsOutput",
"type": "object"
}
```
## Limits & Quotas
- Rate limits depend on your Crunchbase plan tier (Basic, Pro, Enterprise).
- Enterprise plans typically allow higher request volumes; check your account dashboard for current limits.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Crunchbase](https://www.crunchbase.com)
---
# Customer.io Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/customerio
Marketing automation platform for personalized customer experiences through email, SMS, and push notifications
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/customerio/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Customer.io** to any ModuleX agent or workflow. Customer profile sync, event tracking, and manual-segment membership management against the Customer.io Track API v1.
**Categories**: Marketing & Advertising · Marketing & Email · Social Media · Customer Support · **Auth**: API Key · **Actions**: 3
## Authentication
### API Key Authentication
Authenticate using your Customer.io Site ID and API Key
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Site ID | Your Customer.io Site ID (Settings > Workspace Settings > API Credentials) | No | `xxxxxxxx-xxxx-xxxx` |
| API Key | Your Customer.io Tracking API Key (Settings > Workspace Settings > API Credentials) | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
| Region | Customer.io data region: 'US' (default, track.customer.io) or 'EU' (track-eu.customer.io). Must match the workspace's region. | No | `US` |
## Available Actions
### Parameters
The unique identifier for the customer
The customer's email address
UNIX timestamp from when the user was created in your system
Custom attributes (name, plan, company, etc.)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"customer_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Customer Id"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
}
},
"required": [
"success"
],
"title": "CreateOrUpdateCustomerOutput",
"type": "object"
}
```
### Parameters
The unique identifier for the customer
The name of the event to track
Event type modifier (set to 'page' for page views)
Custom data to include with the event
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"customer_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Customer Id"
},
"event_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Event Name"
}
},
"required": [
"success"
],
"title": "SendEventOutput",
"type": "object"
}
```
### Parameters
The segment ID
List of customer IDs (max 1000)
The type of IDs: 'id', 'email', or 'cio_id' (Default: `id`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"segment_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Segment Id"
},
"customer_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Customer Count"
},
"id_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id Type"
}
},
"required": [
"success"
],
"title": "AddCustomersToSegmentOutput",
"type": "object"
}
```
## Limits & Quotas
- Manual segment add: max 1000 customer IDs per call (enforced
client-side; the tool returns `success=False` if the cap is
exceeded).
- All actions are idempotent on the Customer.io side.
## Related integrations
## Links
- [Customer.io](https://customer.io)
---
# Databricks Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/databricks
Manage Databricks jobs, runs, SQL warehouses, and vector search indexes.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/databricks/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Databricks** to any ModuleX agent or workflow. Manage Databricks jobs, runs, SQL warehouses, and vector search indexes via the Databricks REST API (`{domain}.cloud.databricks.com`).
**Categories**: Analytics & Data · Data Engineering · Analytics · Machine Learning · **Auth**: Databricks Personal Access Token · **Actions**: 41
## Authentication
### Databricks Personal Access Token
Authenticate using your Databricks workspace domain and a personal access token.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Workspace Domain | Your Databricks workspace subdomain (the part before .cloud.databricks.com). | Yes | `my-workspace` |
| Access Token | A Databricks personal access token. | Yes | `dapi0123456789abcdef0123456789abcdef` |
## Available Actions
### Parameters
Identifier of a job. If omitted with all_queued_runs=true, cancels all queued runs in the workspace.
Cancel all queued runs. If no job_id is provided, all queued runs in the workspace are canceled.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "CancelAllRunsOutput",
"type": "object"
}
```
### Parameters
Identifier of the run to cancel.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "CancelRunOutput",
"type": "object"
}
```
### Parameters
The name of the vector search endpoint to create.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateEndpointOutput",
"type": "object"
}
```
### Parameters
JSON string of task specifications for this job.
An optional name for the job.
JSON string of tags associated with the job.
JSON string of job cluster specifications.
JSON string of email notification settings.
JSON string of webhook notification settings.
Timeout in seconds applied to each run of this job.
JSON string of schedule definition with quartz_cron_expression and timezone_id.
Maximum number of concurrent runs for the job.
JSON string specifying a remote Git repository for task source code.
JSON string of permissions to set on the job.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"job_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Job Id"
}
},
"required": [
"success"
],
"title": "CreateJobOutput",
"type": "object"
}
```
### Parameters
A human-readable name for the warehouse.
Size of the cluster: 2X-Small, X-Small, Small, Medium, Large, X-Large, 2X-Large, 3X-Large, 4X-Large.
Minutes of inactivity before auto-stop. 0 disables. Must be 0 or >= 10. (Default: `10`)
Minimum number of clusters to maintain. (Default: `1`)
Maximum number of clusters for autoscaling. (Default: `1`)
Whether to use Photon optimized clusters.
Whether to use serverless compute.
Warehouse type: TYPE_UNSPECIFIED, CLASSIC, or PRO.
Spot instance policy: POLICY_UNSPECIFIED, COST_OPTIMIZED, RELIABILITY_OPTIMIZED.
JSON string of channel details.
JSON string of custom key-value tags.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateSqlWarehouseOutput",
"type": "object"
}
```
### Parameters
A unique name for the index (e.g., main_catalog.docs.en_wiki_index).
The name of the vector search endpoint.
Type of index: DELTA_SYNC or DIRECT_ACCESS.
The primary key column for the index.
The Delta table backing the index (required for DELTA_SYNC).
JSON array of column names to sync from the source Delta table.
JSON array of embedding source column configs.
The schema of the index in JSON format (required for DIRECT_ACCESS). Sent on the wire as `schema_json`.
Pipeline type: TRIGGERED or CONTINUOUS. (Default: `TRIGGERED`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateVectorSearchIndexOutput",
"type": "object"
}
```
### Parameters
The name of the vector search endpoint to delete.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "DeleteEndpointOutput",
"type": "object"
}
```
### Parameters
Identifier of the job to delete.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "DeleteJobOutput",
"type": "object"
}
```
### Parameters
Identifier of the run to delete.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "DeleteRunOutput",
"type": "object"
}
```
### Parameters
The ID of the SQL Warehouse to delete.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "DeleteSqlWarehouseOutput",
"type": "object"
}
```
### Parameters
The name of the vector search index to delete.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "DeleteVectorSearchIndexOutput",
"type": "object"
}
```
### Parameters
The name of the vector search index.
JSON array of primary key values to delete.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "DeleteVectorSearchIndexDataOutput",
"type": "object"
}
```
### Parameters
The ID of the SQL Warehouse to edit.
New logical name for the warehouse.
Size of clusters: 2X-Small, X-Small, Small, Medium, Large, X-Large, 2X-Large, 3X-Large, 4X-Large.
Minutes of inactivity before auto-stop. 0 disables. Must be 0 or >= 10.
Minimum number of clusters.
Maximum number of clusters for autoscaling.
Whether to use Photon optimized clusters.
Whether to use serverless compute.
Warehouse type: TYPE_UNSPECIFIED, CLASSIC, or PRO.
Spot instance policy: POLICY_UNSPECIFIED, COST_OPTIMIZED, RELIABILITY_OPTIMIZED.
JSON string of custom key-value tags.
JSON string of channel details.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "EditSqlWarehouseOutput",
"type": "object"
}
```
### Parameters
Identifier of the run to export.
Which views to export: CODE, DASHBOARDS, or ALL. Defaults to CODE.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "ExportRunOutput",
"type": "object"
}
```
### Parameters
The name of the vector search endpoint.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetEndpointOutput",
"type": "object"
}
```
### Parameters
Identifier of the job.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetJobOutput",
"type": "object"
}
```
### Parameters
Identifier of the job.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetJobPermissionsOutput",
"type": "object"
}
```
### Parameters
Identifier of the run.
Whether to include the repair history in the response.
Whether to include resolved parameter values in the response.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetRunOutput",
"type": "object"
}
```
### Parameters
Identifier of the run.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetRunOutputOutput",
"type": "object"
}
```
### Parameters
The ID of the SQL Warehouse.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetSqlWarehouseOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetSqlWarehouseConfigOutput",
"type": "object"
}
```
### Parameters
The ID of the SQL Warehouse.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetSqlWarehousePermissionsOutput",
"type": "object"
}
```
### Parameters
The name of the vector search index.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetVectorSearchIndexOutput",
"type": "object"
}
```
### Parameters
Maximum number of endpoints to return. (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"endpoints": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Endpoints",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListEndpointsOutput",
"type": "object"
}
```
### Parameters
Whether to include task and cluster details in the response.
Optional name to filter on.
Maximum number of API page requests to make (1-10).
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"jobs": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Jobs",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListJobsOutput",
"type": "object"
}
```
### Parameters
Identifier of a job to filter runs.
Set to true to return only active runs.
Maximum number of runs to return. (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"runs": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Runs",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListRunsOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"warehouses": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Warehouses",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListSqlWarehousesOutput",
"type": "object"
}
```
### Parameters
The name of the vector search endpoint.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"indexes": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Indexes",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListVectorSearchIndexesOutput",
"type": "object"
}
```
### Parameters
The name of the vector search index.
JSON array of column names to include in the response.
Free-text query for semantic search.
JSON array of floats representing the embedding vector.
JSON string representing query filters.
Number of results to return. (Default: `10`)
Whether to include embedding vectors in the results.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "QueryVectorSearchIndexOutput",
"type": "object"
}
```
### Parameters
Identifier of the run to repair.
JSON array of task keys to repair.
If true, repair all failed tasks.
Controls whether the pipeline should perform a full refresh.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"repair_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Repair Id"
}
},
"required": [
"success"
],
"title": "RepairRunOutput",
"type": "object"
}
```
### Parameters
Identifier of the job.
JSON string of the new settings that fully replaces all existing job settings.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "ResetJobOutput",
"type": "object"
}
```
### Parameters
Identifier of the job to run.
JSON array of parameters for jobs with JAR tasks.
JSON object of key-value pairs for notebook tasks.
JSON array of parameters for Python tasks.
JSON array of parameters for spark submit tasks.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"run_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Run Id"
},
"number_in_job": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Number In Job"
}
},
"required": [
"success"
],
"title": "RunJobNowOutput",
"type": "object"
}
```
### Parameters
The name of the vector search index.
Primary key of the last entry returned in the previous scan. Leave empty to start from the beginning.
Number of results to return. (Default: `10`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "ScanVectorSearchIndexOutput",
"type": "object"
}
```
### Parameters
Identifier of the job.
JSON string of permission objects with user_name/group_name/service_principal_name and permission_level.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "SetJobPermissionsOutput",
"type": "object"
}
```
### Parameters
Instance profile ARN for IAM role (AWS).
Service account email for GCP workspaces.
Security policy: NONE or DATA_ACCESS_CONTROL.
JSON string of channel details.
JSON array of enabled warehouse type objects.
JSON array of general config key/value pairs.
JSON array of global parameter key/value pairs.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "SetSqlWarehouseConfigOutput",
"type": "object"
}
```
### Parameters
The ID of the SQL Warehouse.
JSON string of access control entries with user_name/group_name/service_principal_name and permission_level.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "SetSqlWarehousePermissionsOutput",
"type": "object"
}
```
### Parameters
The ID of the SQL Warehouse to start.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "StartSqlWarehouseOutput",
"type": "object"
}
```
### Parameters
The ID of the SQL Warehouse to stop.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "StopSqlWarehouseOutput",
"type": "object"
}
```
### Parameters
The name of the vector search index to synchronize.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "SyncVectorSearchIndexOutput",
"type": "object"
}
```
### Parameters
Identifier of the job to update.
JSON string of updated job settings (only fields to change).
JSON array of field paths to remove from the job settings.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "UpdateJobOutput",
"type": "object"
}
```
### Parameters
The name of the vector search index.
JSON array of row objects to upsert.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "UpsertVectorSearchIndexDataOutput",
"type": "object"
}
```
## Limits & Quotas
- Databricks API rate limits vary by endpoint and workspace tier. Consult your workspace admin for specific limits.
- Jobs API: typically 30 requests/second per workspace.
- Vector Search API: limits depend on endpoint configuration and provisioned capacity.
- SQL Warehouses API: standard REST API limits apply.
- Error model: non-2xx responses are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Databricks](https://www.databricks.com)
---
# Datadog Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/datadog
Infrastructure monitoring, log management, and application performance platform
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/datadog/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Datadog** to any ModuleX agent or workflow. Infrastructure monitoring, log management, and application performance platform via the Datadog REST API (`api.{region}/api`).
**Categories**: Monitoring & Observability · Developer Tools & Infrastructure · **Auth**: Datadog API Keys · **Actions**: 11
## Authentication
### Datadog API Keys
Authenticate using your Datadog API key and Application key
Go to https://app.datadoghq.com/organization-settings/api-keys and sign in
Copy or create a new API key
Go to https://app.datadoghq.com/organization-settings/application-keys
Copy or create a new Application key
Paste both keys below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| API Key | Your Datadog API key from Organization Settings > API Keys | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
| Application Key | Your Datadog Application key from Organization Settings > Application Keys | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"region": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Region"
},
"label": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Label"
},
"api_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Api Url"
}
},
"required": [
"success"
],
"title": "GetAccountInfoOutput",
"type": "object"
}
```
### Parameters
The regional site for the Datadog account (e.g. datadoghq.com, us3.datadoghq.com, us5.datadoghq.com, datadoghq.eu, ddog-gov.com)
Metric query string (e.g. avg:system.cpu.user{*} or sum:my.metric{env:prod} by {host})
Start of the query window as POSIX timestamp in seconds
End of the query window as POSIX timestamp in seconds
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"series": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Series",
"type": "array"
},
"from_date": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "From Date"
},
"to_date": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "To Date"
},
"query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Query"
}
},
"required": [
"success"
],
"title": "GetMetricDataOutput",
"type": "object"
}
```
### Parameters
The regional site for the Datadog account (e.g. datadoghq.com, us3.datadoghq.com, us5.datadoghq.com, datadoghq.eu, ddog-gov.com)
The name of the timeseries metric
Points as a JSON object where keys are Unix timestamps (seconds) and values are numeric (e.g. {"1640995200": 1.0})
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"errors": {
"items": {
"type": "string"
},
"title": "Errors",
"type": "array"
}
},
"required": [
"success"
],
"title": "PostMetricDataOutput",
"type": "object"
}
```
### Parameters
The regional site for the Datadog account (e.g. datadoghq.com, us3.datadoghq.com, us5.datadoghq.com, datadoghq.eu, ddog-gov.com)
If true, only return dashboards that are shared
Maximum number of dashboards to return
Offset for pagination
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"dashboards": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Dashboards",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchDashboardsOutput",
"type": "object"
}
```
### Parameters
The regional site for the Datadog account (e.g. datadoghq.com, us3.datadoghq.com, us5.datadoghq.com, datadoghq.eu, ddog-gov.com)
POSIX timestamp (seconds) for the start of the query window; defaults to 24 hours ago
POSIX timestamp (seconds) for the end of the query window; defaults to now
Filter by event priority: normal or low
Comma-separated list of sources to filter events (e.g. nagios,hudson)
Comma-separated list of tags to filter events (e.g. env:prod,role:db)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"events": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Events",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchEventsOutput",
"type": "object"
}
```
### Parameters
The regional site for the Datadog account (e.g. datadoghq.com, us3.datadoghq.com, us5.datadoghq.com, datadoghq.eu, ddog-gov.com)
Filter hosts by name, alias, or tag (e.g. env:production or host:web-01)
Field to sort hosts by: status, apps, cpu, iowait, or load
Direction of sort: asc or desc
Number of hosts to return (max 1000)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"host_list": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Host List",
"type": "array"
},
"total_matching": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Matching"
}
},
"required": [
"success"
],
"title": "SearchHostsOutput",
"type": "object"
}
```
### Parameters
The regional site for the Datadog account (e.g. datadoghq.com, us3.datadoghq.com, us5.datadoghq.com, datadoghq.eu, ddog-gov.com)
Search query to filter incidents using field:value syntax (e.g. state:active or severity:SEV-1)
Number of incidents per page (default 10)
Offset for pagination
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"incidents": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Incidents",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchIncidentsOutput",
"type": "object"
}
```
### Parameters
The regional site for the Datadog account (e.g. datadoghq.com, us3.datadoghq.com, us5.datadoghq.com, datadoghq.eu, ddog-gov.com)
Search query following log search syntax (e.g. service:web-app status:error) (Default: `*`)
Minimum timestamp for logs; supports date math (now-15m), ISO-8601, or epoch ms; defaults to 15 minutes ago
Maximum timestamp for logs; supports date math (now), ISO-8601, or epoch ms; defaults to now
List of log index names to search (defaults to all indexes); element type: string
Maximum number of logs to return per page (default 10, max 1000)
Sort order for results: -timestamp (newest first) or timestamp (oldest first)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"logs": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Logs",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchLogsOutput",
"type": "object"
}
```
### Parameters
The regional site for the Datadog account (e.g. datadoghq.com, us3.datadoghq.com, us5.datadoghq.com, datadoghq.eu, ddog-gov.com)
Filter metrics by host name
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"metrics": {
"items": {
"type": "string"
},
"title": "Metrics",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchMetricsOutput",
"type": "object"
}
```
### Parameters
The regional site for the Datadog account (e.g. datadoghq.com, us3.datadoghq.com, us5.datadoghq.com, datadoghq.eu, ddog-gov.com)
Filter monitors by name, tag, or other attributes (e.g. tag:env:production or type:metric)
Comma-separated list of tags to filter monitors (e.g. env:prod,team:backend)
Page number to return (0-indexed)
Number of monitors per page (default 100)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"monitors": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Monitors",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchMonitorsOutput",
"type": "object"
}
```
### Parameters
The regional site for the Datadog account (e.g. datadoghq.com, us3.datadoghq.com, us5.datadoghq.com, datadoghq.eu, ddog-gov.com)
Number of services per page (default 10)
Page number (0-indexed)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"services": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Services",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchServicesOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limits**: Datadog enforces per-endpoint rate limits; default is 300 requests/minute for most endpoints, 60/min for logs search, and 120/hour for metric submission.
- **Pagination**: Most list endpoints support pagination via `count`/`start` or `page`/`page_size` parameters.
- **Regions**: The API base URL varies by account region. Use `get_account_info` to auto-detect the correct region before calling other tools.
- **Error model**: Non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Datadog](https://www.datadoghq.com)
---
# Daytona Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/daytona
Run AI-generated code in secure, isolated cloud sandboxes. Create and manage sandboxes, execute shell commands, run Python, JavaScript, or TypeScript code, transfer files, and clone Git repositories.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/daytona/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Daytona** to any ModuleX agent or workflow. Run AI-generated code and shell commands in secure, isolated cloud sandboxes via the Daytona REST API (`app.daytona.io`) and per-sandbox toolbox API (`proxy.app.daytona.io/toolbox`). Create and manage sandboxes, execute commands, run Python/JavaScript/TypeScript, transfer files, and clone Git repositories.
**Categories**: Developer Tools & Infrastructure · Cloud · Automation · **Auth**: API Key · **Actions**: 12
## Authentication
### API Key Authentication
Authenticate using your Daytona API key
Go to https://app.daytona.io and sign up or log in
Open the dashboard and navigate to the 'Keys' (API Keys) section
Create a new API key and copy it
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Daytona API Key | Your Daytona API key from app.daytona.io | Yes | `-` |
## Available Actions
### Parameters
ID or name of the snapshot to create the sandbox from (uses default if empty)
Name for the sandbox (defaults to the sandbox ID)
Region where the sandbox will be created (e.g., us, eu)
User associated with the sandbox
Environment variables to set in the sandbox as key-value pairs
Labels to attach to the sandbox as key-value pairs
CPU cores to allocate to the sandbox
Memory to allocate to the sandbox in GB
Disk space to allocate to the sandbox in GB
Auto-stop interval in minutes (0 disables auto-stop)
Auto-archive interval in minutes (0 uses the maximum interval)
Auto-delete interval in minutes (negative disables, 0 deletes immediately on stop)
Whether the sandbox HTTP preview is publicly accessible
### Response
```json
{
"$defs": {
"SandboxSummary": {
"additionalProperties": false,
"description": "Normalized summary of a Daytona sandbox.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"snapshot": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Snapshot"
},
"target": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Target"
},
"cpu": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Cpu"
},
"gpu": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Gpu"
},
"memory": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Memory"
},
"disk": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Disk"
},
"labels": {
"additionalProperties": true,
"title": "Labels",
"type": "object"
},
"public": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Public"
},
"error_reason": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error Reason"
},
"auto_stop_interval": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Auto Stop Interval"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"title": "SandboxSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"sandbox": {
"anyOf": [
{
"$ref": "#/$defs/SandboxSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateSandboxOutput",
"type": "object"
}
```
### Parameters
ID of the sandbox to run the code in
Code to run
Language of the code: python, javascript, or typescript
Environment variables to set for the run as key-value pairs
Timeout in seconds (defaults to 10 seconds)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"exit_code": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Exit Code"
},
"result": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
},
"artifacts": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Artifacts"
}
},
"required": [
"success"
],
"title": "RunCodeOutput",
"type": "object"
}
```
### Parameters
ID of the sandbox to execute the command in
Shell command to execute
Working directory for the command (defaults to the sandbox working directory)
Environment variables to set for the command as key-value pairs
Timeout in seconds (defaults to 10 seconds)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"exit_code": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Exit Code"
},
"result": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "ExecuteCommandOutput",
"type": "object"
}
```
### Parameters
ID of the sandbox to upload the file to
Destination path in the sandbox (a trailing slash uploads into that directory using the file name)
Base64-encoded content of the file to upload
Optional file name override
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"uploaded_path": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uploaded Path"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
}
},
"required": [
"success"
],
"title": "UploadFileOutput",
"type": "object"
}
```
### Parameters
ID of the sandbox to download the file from
Path of the file in the sandbox
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"mime_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mime Type"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"content_base64": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Base64"
}
},
"required": [
"success"
],
"title": "DownloadFileOutput",
"type": "object"
}
```
### Parameters
ID of the sandbox to list files in
Directory path to list (defaults to the sandbox working directory)
### Response
```json
{
"$defs": {
"FileInfo": {
"additionalProperties": false,
"description": "A single entry returned by ``list_files``.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"is_dir": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Dir"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"mode": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mode"
},
"permissions": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Permissions"
},
"owner": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Owner"
},
"group": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Group"
},
"modified_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Modified At"
}
},
"title": "FileInfo",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"files": {
"items": {
"$ref": "#/$defs/FileInfo"
},
"title": "Files",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListFilesOutput",
"type": "object"
}
```
### Parameters
ID of the sandbox to clone the repository into
URL of the Git repository to clone
Path in the sandbox to clone the repository into
Branch to clone (defaults to the default branch)
Specific commit to check out after cloning
Username for authenticating to private repositories
Password or personal access token for private repositories
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"repo_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Repo Url"
},
"clone_path": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Clone Path"
}
},
"required": [
"success"
],
"title": "GitCloneOutput",
"type": "object"
}
```
### Parameters
Maximum number of sandboxes to return (1-200)
Filter sandboxes by name prefix (case-insensitive)
Filter sandboxes by labels as key-value pairs
Pagination cursor from a previous response
### Response
```json
{
"$defs": {
"SandboxSummary": {
"additionalProperties": false,
"description": "Normalized summary of a Daytona sandbox.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"snapshot": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Snapshot"
},
"target": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Target"
},
"cpu": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Cpu"
},
"gpu": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Gpu"
},
"memory": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Memory"
},
"disk": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Disk"
},
"labels": {
"additionalProperties": true,
"title": "Labels",
"type": "object"
},
"public": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Public"
},
"error_reason": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error Reason"
},
"auto_stop_interval": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Auto Stop Interval"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"title": "SandboxSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"sandboxes": {
"items": {
"$ref": "#/$defs/SandboxSummary"
},
"title": "Sandboxes",
"type": "array"
},
"next_cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Cursor"
}
},
"required": [
"success"
],
"title": "ListSandboxesOutput",
"type": "object"
}
```
### Parameters
ID or name of the sandbox
### Response
```json
{
"$defs": {
"SandboxSummary": {
"additionalProperties": false,
"description": "Normalized summary of a Daytona sandbox.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"snapshot": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Snapshot"
},
"target": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Target"
},
"cpu": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Cpu"
},
"gpu": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Gpu"
},
"memory": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Memory"
},
"disk": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Disk"
},
"labels": {
"additionalProperties": true,
"title": "Labels",
"type": "object"
},
"public": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Public"
},
"error_reason": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error Reason"
},
"auto_stop_interval": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Auto Stop Interval"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"title": "SandboxSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"sandbox": {
"anyOf": [
{
"$ref": "#/$defs/SandboxSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetSandboxOutput",
"type": "object"
}
```
### Parameters
ID or name of the sandbox
### Response
```json
{
"$defs": {
"SandboxSummary": {
"additionalProperties": false,
"description": "Normalized summary of a Daytona sandbox.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"snapshot": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Snapshot"
},
"target": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Target"
},
"cpu": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Cpu"
},
"gpu": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Gpu"
},
"memory": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Memory"
},
"disk": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Disk"
},
"labels": {
"additionalProperties": true,
"title": "Labels",
"type": "object"
},
"public": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Public"
},
"error_reason": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error Reason"
},
"auto_stop_interval": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Auto Stop Interval"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"title": "SandboxSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"sandbox": {
"anyOf": [
{
"$ref": "#/$defs/SandboxSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "StartSandboxOutput",
"type": "object"
}
```
### Parameters
ID or name of the sandbox
### Response
```json
{
"$defs": {
"SandboxSummary": {
"additionalProperties": false,
"description": "Normalized summary of a Daytona sandbox.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"snapshot": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Snapshot"
},
"target": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Target"
},
"cpu": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Cpu"
},
"gpu": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Gpu"
},
"memory": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Memory"
},
"disk": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Disk"
},
"labels": {
"additionalProperties": true,
"title": "Labels",
"type": "object"
},
"public": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Public"
},
"error_reason": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error Reason"
},
"auto_stop_interval": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Auto Stop Interval"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"title": "SandboxSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"sandbox": {
"anyOf": [
{
"$ref": "#/$defs/SandboxSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "StopSandboxOutput",
"type": "object"
}
```
### Parameters
ID or name of the sandbox
### Response
```json
{
"$defs": {
"SandboxSummary": {
"additionalProperties": false,
"description": "Normalized summary of a Daytona sandbox.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"snapshot": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Snapshot"
},
"target": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Target"
},
"cpu": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Cpu"
},
"gpu": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Gpu"
},
"memory": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Memory"
},
"disk": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Disk"
},
"labels": {
"additionalProperties": true,
"title": "Labels",
"type": "object"
},
"public": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Public"
},
"error_reason": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error Reason"
},
"auto_stop_interval": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Auto Stop Interval"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"title": "SandboxSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"sandbox": {
"anyOf": [
{
"$ref": "#/$defs/SandboxSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "DeleteSandboxOutput",
"type": "object"
}
```
## Limits & Quotas
- **Downloads**: capped at 100MB; larger files return
`success=False` with an error. Content is returned base64-encoded
inline in `content_base64`.
- **Uploads**: provide file bytes via the `file_content_base64`
parameter.
- **Sandbox IDs**: `get_sandbox`, `start_sandbox`, `stop_sandbox`, and
`delete_sandbox` accept either the sandbox ID or its name; all other
sandbox-scoped operations require the ID.
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Daytona](https://www.daytona.io)
---
# DigitalOcean Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/digital-ocean
Cloud infrastructure platform for deploying and managing Droplets, domains, and SSH keys via the DigitalOcean API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/digital_ocean/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **DigitalOcean** to any ModuleX agent or workflow. Cloud infrastructure management via the DigitalOcean REST API (`api.digitalocean.com/v2`). Create and manage Droplets, domains, SSH keys, and snapshots.
**Categories**: Developer Tools & Infrastructure · Cloud Infrastructure · Devops · **Auth**: OAuth2 · **Actions**: 6
## Authentication
### OAuth2 Authentication
Connect using DigitalOcean OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | DigitalOcean OAuth App Client ID | Yes | `-` |
| Client Secret | DigitalOcean OAuth App Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://cloud.digitalocean.com/v1/oauth/authorize`
- **Token URL**: `https://cloud.digitalocean.com/v1/oauth/token`
- **Scopes**: `read`, `write`
## Available Actions
### Parameters
A human-readable display name for this key, used to easily identify the SSH keys when they are displayed
The entire public key string that will be embedded into the root user's authorized_keys file
### Response
```json
{
"$defs": {
"SshKeyResource": {
"additionalProperties": false,
"description": "An SSH key on the DigitalOcean account.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"fingerprint": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Fingerprint"
},
"public_key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Public Key"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
}
},
"title": "SshKeyResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"ssh_key": {
"anyOf": [
{
"$ref": "#/$defs/SshKeyResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "AddSshKeyOutput",
"type": "object"
}
```
### Parameters
The domain name in standard domain.TLD format (e.g. example.com)
An IP address to automatically create an A record pointing to the apex domain
### Response
```json
{
"$defs": {
"DomainResource": {
"additionalProperties": false,
"description": "A domain registered in DigitalOcean DNS.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"ttl": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Ttl"
},
"zone_file": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Zone File"
}
},
"title": "DomainResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"domain": {
"anyOf": [
{
"$ref": "#/$defs/DomainResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateDomainOutput",
"type": "object"
}
```
### Parameters
Human-readable string used as the Droplet display name
Region slug where the Droplet will be deployed (e.g. nyc1, sfo1, ams3)
Image ID or slug for the base image (e.g. ubuntu-22-04-x64)
Size slug for the Droplet (e.g. s-1vcpu-1gb)
List of Block Storage volume IDs to attach to the Droplet
List of SSH key IDs or fingerprints to embed in the Droplet's root account
Whether automated backups should be enabled
Whether IPv6 is enabled on the Droplet
Cloud-init user data or Bash script for first-boot configuration (max 64 KiB)
Whether private networking is enabled for the Droplet
Whether to install the DigitalOcean monitoring agent
List of tag names to apply to the Droplet after creation
### Response
```json
{
"$defs": {
"DropletResource": {
"additionalProperties": false,
"description": "A DigitalOcean Droplet summary.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"memory": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Memory"
},
"vcpus": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Vcpus"
},
"disk": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Disk"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"region": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Region"
},
"image": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Image"
},
"size_slug": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Size Slug"
}
},
"title": "DropletResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"droplet": {
"anyOf": [
{
"$ref": "#/$defs/DropletResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateDropletOutput",
"type": "object"
}
```
### Parameters
The unique identifier of the Droplet to snapshot
The name to give the new snapshot
### Response
```json
{
"$defs": {
"DropletActionResource": {
"additionalProperties": false,
"description": "A DigitalOcean Droplet action.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"started_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Started At"
},
"completed_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Completed At"
},
"resource_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Resource Id"
},
"resource_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Resource Type"
},
"region_slug": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Region Slug"
}
},
"title": "DropletActionResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"action": {
"anyOf": [
{
"$ref": "#/$defs/DropletActionResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateSnapshotOutput",
"type": "object"
}
```
### Parameters
Filter Droplets by a specific tag name
Which page of paginated results to return (Default: `1`)
Number of items returned per page (Default: `50`)
### Response
```json
{
"$defs": {
"DropletResource": {
"additionalProperties": false,
"description": "A DigitalOcean Droplet summary.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"memory": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Memory"
},
"vcpus": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Vcpus"
},
"disk": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Disk"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"region": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Region"
},
"image": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Image"
},
"size_slug": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Size Slug"
}
},
"title": "DropletResource",
"type": "object"
},
"MetaResource": {
"additionalProperties": false,
"description": "Pagination meta from DigitalOcean list responses.",
"properties": {
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
}
},
"title": "MetaResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"droplets": {
"items": {
"$ref": "#/$defs/DropletResource"
},
"title": "Droplets",
"type": "array"
},
"meta": {
"anyOf": [
{
"$ref": "#/$defs/MetaResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "ListAllDropletsOutput",
"type": "object"
}
```
### Parameters
Power action to perform: power_on or power_off
The unique identifier of the Droplet to power on/off
### Response
```json
{
"$defs": {
"DropletActionResource": {
"additionalProperties": false,
"description": "A DigitalOcean Droplet action.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"started_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Started At"
},
"completed_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Completed At"
},
"resource_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Resource Id"
},
"resource_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Resource Type"
},
"region_slug": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Region Slug"
}
},
"title": "DropletActionResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"action": {
"anyOf": [
{
"$ref": "#/$defs/DropletActionResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "TurnonoffDropletOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limit**: 5,000 requests per hour per OAuth token (returns HTTP 429 when exceeded).
- **Droplet creation**: subject to account-level Droplet limits (default 25; request increase via support).
- **Error model**: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [DigitalOcean](https://www.digitalocean.com)
---
# DocuSign Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/docusign
Electronic signature and agreement management via the DocuSign eSignature REST API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/docusign/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **DocuSign** to any ModuleX agent or workflow. Electronic signature and agreement management via the DocuSign eSignature REST API (`account.docusign.com` + per-account base URIs resolved at runtime).
**Categories**: Productivity & Collaboration · Legal · E Signature · Document Management · **Auth**: OAuth2 · **Actions**: 12
## Authentication
### OAuth2 Authentication
Connect using DocuSign OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | DocuSign OAuth App Integration Key (Client ID) | Yes | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
| Client Secret | DocuSign OAuth App Secret Key | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://account.docusign.com/oauth/auth`
- **Token URL**: `https://account.docusign.com/oauth/token`
- **Scopes**: `signature`, `extended`
## Available Actions
### Parameters
DocuSign Account ID
Document Template ID
Subject line of the signature request email
Email message body to the recipient. Overrides the template setting
JSON array of template role objects, each with roleName, name, and email. Example: [{"roleName":"Signer 1","name":"Jane","email":"jane@example.com"}]
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"envelope_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Envelope Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"status_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status Date Time"
},
"uri": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uri"
}
},
"required": [
"success"
],
"title": "CreateSignatureRequestOutput",
"type": "object"
}
```
### Parameters
DocuSign Account ID
Document Template ID
Subject line of the email
Email message body to the recipient. Overrides the template setting
JSON array of template role objects, each with roleName, name, and email
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"envelope_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Envelope Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"status_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status Date Time"
},
"uri": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uri"
}
},
"required": [
"success"
],
"title": "CreateDraftOutput",
"type": "object"
}
```
### Parameters
DocuSign Account ID
Full DocuSign envelope definition as a JSON string. Example: {"emailSubject":"Please sign","status":"sent","documents":[...],"recipients":{"signers":[...]}}
Envelope status override. Use 'created' to save as draft or 'sent' to send immediately. Allowed values: sent, created
When creating a draft from multiple templates, merge template roles and remove empty recipients
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"envelope_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Envelope Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"status_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status Date Time"
},
"uri": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uri"
}
},
"required": [
"success"
],
"title": "CreateEnvelopeOutput",
"type": "object"
}
```
### Parameters
DocuSign Account ID
URL of the document to send. The file will be fetched and base64-encoded for upload to DocuSign
Subject line of the email
Full name of the signer
Email address of the signer
Use 'sent' to send immediately or 'created' to save as draft. Allowed values: sent, created (Default: `sent`)
Document name shown in DocuSign. Defaults to the filename from the URL
File extension. Defaults to the extension from the URL, or 'pdf' if not detected
Recipient ID for the signer (Default: `1`)
Routing order for the signer (Default: `1`)
Set this for embedded signing recipients. The same value is required when creating a recipient view URL
Anchor text in the document where DocuSign places the signature tab. Example: /sn1/ (Default: `/sn1/`)
Horizontal offset in pixels for the signature tab relative to the anchor text (Default: `20`)
Vertical offset in pixels for the signature tab relative to the anchor text (Default: `10`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"envelope_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Envelope Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"status_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status Date Time"
},
"uri": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uri"
}
},
"required": [
"success"
],
"title": "CreateEnvelopeFromFileOutput",
"type": "object"
}
```
### Parameters
DocuSign Account ID
DocuSign envelope ID
URL where DocuSign redirects the signer after the signing session. Must include https://
Recipient ID on the envelope
Convention string describing how your app authenticated the signer. Example: none (Default: `none`)
URL DocuSign pings while the signing session is active
Ping interval in seconds. DocuSign supports 60 to 1200
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
}
},
"required": [
"success"
],
"title": "CreateRecipientViewOutput",
"type": "object"
}
```
### Parameters
DocuSign Account ID
DocuSign envelope ID
Comma-separated additional information to include. Allowed values: custom_fields, documents, extensions, folders, recipients, tabs
### Response
```json
{
"$defs": {
"EnvelopeSummary": {
"additionalProperties": false,
"properties": {
"envelope_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Envelope Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"email_subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Subject"
},
"status_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status Date Time"
},
"uri": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uri"
},
"sender_user_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sender User Name"
},
"sender_email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sender Email"
},
"created_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created Date Time"
},
"sent_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sent Date Time"
},
"completed_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Completed Date Time"
},
"voided_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Voided Date Time"
},
"voided_reason": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Voided Reason"
}
},
"title": "EnvelopeSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"envelope": {
"anyOf": [
{
"$ref": "#/$defs/EnvelopeSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetEnvelopeOutput",
"type": "object"
}
```
### Parameters
DocuSign Account ID
Return envelopes changed on or after this ISO 8601 datetime, e.g. 2026-04-01T00:00:00Z. Defaults to 30 days ago
Return envelopes changed on or before this ISO 8601 datetime
Comma-separated envelope statuses. Allowed values: any, completed, created, declined, deleted, delivered, processing, sent, signed, timedout, voided
Filter by recipient or sender email address
Search text matched against envelope metadata
Comma-separated folder IDs to filter by
Number of envelopes per page (Default: `100`)
Zero-based result offset (Default: `0`)
Sort order. Allowed values: asc, desc
Field to sort by. Allowed values: action_required, created, completed, sent, signer_list, status, subject, last_modified
When true, follow pagination until no pages remain or max_pages is reached (Default: `false`)
Maximum pages to retrieve when fetch_all is true (Default: `10`)
### Response
```json
{
"$defs": {
"EnvelopeSummary": {
"additionalProperties": false,
"properties": {
"envelope_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Envelope Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"email_subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Subject"
},
"status_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status Date Time"
},
"uri": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uri"
},
"sender_user_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sender User Name"
},
"sender_email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sender Email"
},
"created_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created Date Time"
},
"sent_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sent Date Time"
},
"completed_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Completed Date Time"
},
"voided_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Voided Date Time"
},
"voided_reason": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Voided Reason"
}
},
"title": "EnvelopeSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"envelopes": {
"items": {
"$ref": "#/$defs/EnvelopeSummary"
},
"title": "Envelopes",
"type": "array"
},
"result_set_size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Result Set Size"
},
"total_set_size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Set Size"
}
},
"required": [
"success"
],
"title": "ListEnvelopesOutput",
"type": "object"
}
```
### Parameters
DocuSign Account ID
DocuSign envelope ID
Whether to include tab information for each document (Default: `false`)
Whether to include document metadata (Default: `false`)
### Response
```json
{
"$defs": {
"DocumentSummary": {
"additionalProperties": false,
"properties": {
"document_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Document Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"uri": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uri"
},
"order": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Order"
},
"pages": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Pages"
}
},
"title": "DocumentSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"documents": {
"items": {
"$ref": "#/$defs/DocumentSummary"
},
"title": "Documents",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListDocumentsOutput",
"type": "object"
}
```
### Parameters
DocuSign Account ID
DocuSign envelope ID
Whether to include each recipient's tabs (Default: `false`)
Whether to include extended recipient information (Default: `false`)
Whether to include metadata (Default: `false`)
### Response
```json
{
"$defs": {
"RecipientSummary": {
"additionalProperties": false,
"properties": {
"recipient_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Recipient Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"routing_order": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Routing Order"
},
"client_user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Client User Id"
},
"signed_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Signed Date Time"
},
"delivered_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Delivered Date Time"
}
},
"title": "RecipientSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"signers": {
"items": {
"$ref": "#/$defs/RecipientSummary"
},
"title": "Signers",
"type": "array"
},
"carbon_copies": {
"items": {
"$ref": "#/$defs/RecipientSummary"
},
"title": "Carbon Copies",
"type": "array"
},
"agents": {
"items": {
"$ref": "#/$defs/RecipientSummary"
},
"title": "Agents",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListRecipientsOutput",
"type": "object"
}
```
### Parameters
DocuSign Account ID
DocuSign envelope ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"envelope_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Envelope Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
}
},
"required": [
"success"
],
"title": "SendEnvelopeOutput",
"type": "object"
}
```
### Parameters
DocuSign Account ID
DocuSign envelope ID
Download type. Allowed values: combined (All Documents PDF), archive (All Documents Zip), certificate (Certificate PDF), portfolio (Portfolio PDF)
Filename including extension (.pdf or .zip) for the downloaded content
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"content_base64": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Base64"
},
"filename": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Filename"
},
"content_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Type"
}
},
"required": [
"success"
],
"title": "DownloadDocumentsOutput",
"type": "object"
}
```
### Parameters
DocuSign Account ID
DocuSign envelope ID
Reason the envelope is being voided. Visible in DocuSign audit history
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"envelope_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Envelope Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
}
},
"required": [
"success"
],
"title": "VoidEnvelopeOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limits**: DocuSign enforces per-account rate limits; the eSignature REST API allows approximately 1,000 requests per 15 minutes for production accounts. Demo/sandbox accounts have lower limits.
- **Polling intervals**: For envelope status polling, DocuSign recommends no more than once per 15 minutes.
- **File size**: Maximum document size is 25 MB per document.
- **Error model**: Non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising. Plan for retries on the agent side based on the error string.
## Related integrations
## Links
- [DocuSign](https://www.docusign.com)
---
# Dropbox Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/dropbox
Cloud file storage, sharing, and collaboration platform
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/dropbox/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Dropbox** to any ModuleX agent or workflow. Cloud file storage, sharing, and collaboration via the Dropbox HTTP API (`api.dropboxapi.com/2`).
**Categories**: Cloud Infrastructure · Productivity & Collaboration · File Storage · Cloud Storage · **Auth**: OAuth2 · **Actions**: 12
## Authentication
### OAuth2 Authentication
Connect using Dropbox OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Dropbox OAuth App Client ID | Yes | `xxxxxxxxxxxxxxx` |
| Client Secret | Dropbox OAuth App Client Secret | Yes | `xxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://www.dropbox.com/oauth2/authorize`
- **Token URL**: `https://api.dropboxapi.com/oauth2/token`
- **Scopes**: `files.metadata.read`, `files.metadata.write`, `files.content.read`, `files.content.write`, `sharing.read`, `sharing.write`, `account_info.read`
## Available Actions
### Parameters
The new folder name
Parent folder path where the new folder will be created (empty string for root) (Default: ``)
If true, Dropbox will autorename the folder if there is a conflict (Default: `true`)
### Response
```json
{
"$defs": {
"FileMetadata": {
"additionalProperties": false,
"description": "Metadata for a file or folder returned by the Dropbox API.",
"properties": {
".tag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": ".Tag"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"path_display": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path Display"
},
"path_lower": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path Lower"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"rev": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rev"
},
"content_hash": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Hash"
},
"server_modified": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Server Modified"
},
"client_modified": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Client Modified"
},
"is_downloadable": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Downloadable"
}
},
"title": "FileMetadata",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"metadata": {
"anyOf": [
{
"$ref": "#/$defs/FileMetadata"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateFolderOutput",
"type": "object"
}
```
### Parameters
The search query string
Folder path to restrict the search to (empty string for all) (Default: ``)
Sort order: relevance, last_modified_time
Restrict to file status: active, deleted
If true, restricts search to filenames only
Maximum number of results to return (defaults to 100)
### Response
```json
{
"$defs": {
"FileMetadata": {
"additionalProperties": false,
"description": "Metadata for a file or folder returned by the Dropbox API.",
"properties": {
".tag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": ".Tag"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"path_display": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path Display"
},
"path_lower": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path Lower"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"rev": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rev"
},
"content_hash": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Hash"
},
"server_modified": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Server Modified"
},
"client_modified": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Client Modified"
},
"is_downloadable": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Downloadable"
}
},
"title": "FileMetadata",
"type": "object"
},
"SearchMatch": {
"additionalProperties": false,
"description": "A single search result match.",
"properties": {
"match_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Match Type"
},
"metadata": {
"anyOf": [
{
"$ref": "#/$defs/FileMetadata"
},
{
"type": "null"
}
],
"default": null
}
},
"title": "SearchMatch",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"matches": {
"items": {
"$ref": "#/$defs/SearchMatch"
},
"title": "Matches",
"type": "array"
},
"has_more": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has More"
}
},
"required": [
"success"
],
"title": "SearchFileFoldersOutput",
"type": "object"
}
```
### Parameters
The folder path to list contents of (empty string for root)
If true, list contents of all subfolders recursively (Default: `true`)
If true, include files and folders that were deleted (Default: `false`)
If true, include entries under mounted folders (app, shared, team) (Default: `false`)
If true, include non-downloadable files like Google Docs (Default: `true`)
Maximum number of entries to return (defaults to 100)
### Response
```json
{
"$defs": {
"FileMetadata": {
"additionalProperties": false,
"description": "Metadata for a file or folder returned by the Dropbox API.",
"properties": {
".tag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": ".Tag"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"path_display": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path Display"
},
"path_lower": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path Lower"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"rev": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rev"
},
"content_hash": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Hash"
},
"server_modified": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Server Modified"
},
"client_modified": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Client Modified"
},
"is_downloadable": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Downloadable"
}
},
"title": "FileMetadata",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"entries": {
"items": {
"$ref": "#/$defs/FileMetadata"
},
"title": "Entries",
"type": "array"
},
"has_more": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has More"
}
},
"required": [
"success"
],
"title": "ListFileFoldersOutput",
"type": "object"
}
```
### Parameters
Path of the file or folder to delete
### Response
```json
{
"$defs": {
"FileMetadata": {
"additionalProperties": false,
"description": "Metadata for a file or folder returned by the Dropbox API.",
"properties": {
".tag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": ".Tag"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"path_display": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path Display"
},
"path_lower": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path Lower"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"rev": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rev"
},
"content_hash": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Hash"
},
"server_modified": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Server Modified"
},
"client_modified": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Client Modified"
},
"is_downloadable": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Downloadable"
}
},
"title": "FileMetadata",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"metadata": {
"anyOf": [
{
"$ref": "#/$defs/FileMetadata"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "DeleteFileFolderOutput",
"type": "object"
}
```
### Parameters
Path of the file or folder to move
Destination folder path (file name is appended automatically)
If true, autorename to avoid conflicts (Default: `false`)
Allow moves that result in ownership transfer (Default: `false`)
### Response
```json
{
"$defs": {
"FileMetadata": {
"additionalProperties": false,
"description": "Metadata for a file or folder returned by the Dropbox API.",
"properties": {
".tag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": ".Tag"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"path_display": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path Display"
},
"path_lower": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path Lower"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"rev": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rev"
},
"content_hash": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Hash"
},
"server_modified": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Server Modified"
},
"client_modified": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Client Modified"
},
"is_downloadable": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Downloadable"
}
},
"title": "FileMetadata",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"metadata": {
"anyOf": [
{
"$ref": "#/$defs/FileMetadata"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "MoveFileFolderOutput",
"type": "object"
}
```
### Parameters
Path of the file or folder to rename
The new name (include file extension for files)
If true, autorename to avoid conflicts (Default: `false`)
Allow renames that result in ownership transfer (Default: `false`)
### Response
```json
{
"$defs": {
"FileMetadata": {
"additionalProperties": false,
"description": "Metadata for a file or folder returned by the Dropbox API.",
"properties": {
".tag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": ".Tag"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"path_display": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path Display"
},
"path_lower": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path Lower"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"rev": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rev"
},
"content_hash": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Hash"
},
"server_modified": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Server Modified"
},
"client_modified": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Client Modified"
},
"is_downloadable": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Downloadable"
}
},
"title": "FileMetadata",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"metadata": {
"anyOf": [
{
"$ref": "#/$defs/FileMetadata"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "RenameFileFolderOutput",
"type": "object"
}
```
### Parameters
File name including extension (e.g. notes.txt)
Folder path where the file will be created (empty string for root) (Default: ``)
The text content of the new file
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"path_display": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path Display"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"rev": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rev"
},
"content_hash": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Hash"
}
},
"required": [
"success"
],
"title": "CreateTextFileOutput",
"type": "object"
}
```
### Parameters
File name including extension
Folder path (empty string for root) (Default: ``)
The text content to write or append
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"path_display": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path Display"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"rev": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rev"
},
"content_hash": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Hash"
}
},
"required": [
"success"
],
"title": "CreateOrAppendToTextFileOutput",
"type": "object"
}
```
### Parameters
Path of the file or folder to share
Enable password protection on the shared link (Default: `false`)
Password for the shared link (if require_password is true)
Expiration timestamp in ISO 8601 format (e.g. 2024-07-18T20:00:00Z)
Link audience: public, team, no_one
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"path_lower": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path Lower"
},
"link_permissions": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Link Permissions"
}
},
"required": [
"success"
],
"title": "CreateUpdateShareLinkOutput",
"type": "object"
}
```
### Parameters
File or folder path to list shared links for (optional, lists all if empty)
### Response
```json
{
"$defs": {
"SharedLinkInfo": {
"additionalProperties": false,
"description": "Metadata for a shared link.",
"properties": {
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"path_lower": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path Lower"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"expires": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Expires"
},
"link_permissions": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Link Permissions"
}
},
"title": "SharedLinkInfo",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"links": {
"items": {
"$ref": "#/$defs/SharedLinkInfo"
},
"title": "Links",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListSharedLinksOutput",
"type": "object"
}
```
### Parameters
The URL of the shared link
Password if the shared link is password-protected
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"path_lower": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path Lower"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"link_permissions": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Link Permissions"
}
},
"required": [
"success"
],
"title": "GetSharedLinkMetadataOutput",
"type": "object"
}
```
### Parameters
The file path to list revisions for
Revision mode: path (default, revisions at same path) or id (revisions with same file id)
Maximum number of revision entries to return
### Response
```json
{
"$defs": {
"FileMetadata": {
"additionalProperties": false,
"description": "Metadata for a file or folder returned by the Dropbox API.",
"properties": {
".tag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": ".Tag"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"path_display": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path Display"
},
"path_lower": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path Lower"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"rev": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rev"
},
"content_hash": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Hash"
},
"server_modified": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Server Modified"
},
"client_modified": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Client Modified"
},
"is_downloadable": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Downloadable"
}
},
"title": "FileMetadata",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"entries": {
"items": {
"$ref": "#/$defs/FileMetadata"
},
"title": "Entries",
"type": "array"
},
"is_deleted": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Deleted"
}
},
"required": [
"success"
],
"title": "ListFileRevisionsOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limits**: Dropbox applies per-app and per-user rate limits. Individual apps are limited to approximately 25,000 HTTP requests per month for free-tier apps and higher for production apps.
- **List folder**: Maximum 2,000 entries per single request (pagination via cursor for more).
- **File upload**: Maximum 150 MB per single upload request (content upload endpoint).
- **Error model**: Non-2xx responses are caught and returned as `success=False` + `error` rather than raising. Plan for retries on 429 (rate limit) responses.
## Related integrations
## Links
- [Dropbox](https://www.dropbox.com)
---
# Dropcontact Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/dropcontact
Verify and enrich B2B contacts. Submit a contact with their name, company, website, or LinkedIn URL and receive a verified professional email, phone number, company firmographics, and LinkedIn profile. Enrichment is asynchronous: the request is submitted and polled until the result is ready. Credits are only charged when a verified email is returned.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/dropcontact/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Dropcontact** to any ModuleX agent or workflow. GDPR-compliant B2B contact enrichment against the Dropcontact REST API (`api.dropcontact.com`). Submit a partial contact and receive a verified professional email, phone number, company firmographics, and LinkedIn profile.
**Categories**: Sales · CRM · Enrichment · **Auth**: API Key · **Actions**: 1
## Authentication
### API Key Authentication
Authenticate using your Dropcontact API key
Sign in to your Dropcontact account at https://app.dropcontact.com
Open the 'API & Integrations' settings
Copy your personal API key
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Dropcontact API Key | Your Dropcontact API key (sent as the X-Access-Token header) | Yes | `-` |
## Available Actions
### Parameters
Email address of the contact to enrich
First name of the contact
Last name of the contact
Full name (alternative to first_name + last_name)
Company name
Company website (e.g. acme.com)
French company SIREN number
Phone number
LinkedIn profile URL
Country code (ISO 3166-1 alpha-2, e.g. "US", "FR")
Include SIREN/SIRET enrichment (France only) (Default: `false`)
Language for returned data (e.g. "en", "fr")
### Response
```json
{
"$defs": {
"EmailEntry": {
"additionalProperties": false,
"description": "A single email address with its deliverability qualification.",
"properties": {
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"qualification": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Qualification"
}
},
"title": "EmailEntry",
"type": "object"
}
},
"additionalProperties": false,
"description": "Flat enriched-contact result returned by ``enrich_contact``.",
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Request Id"
},
"email_found": {
"default": false,
"title": "Email Found",
"type": "boolean"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"emails": {
"items": {
"$ref": "#/$defs/EmailEntry"
},
"title": "Emails",
"type": "array"
},
"qualification": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Qualification"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Name"
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Name"
},
"full_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Full Name"
},
"civility": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Civility"
},
"phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Phone"
},
"mobile_phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mobile Phone"
},
"company": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company"
},
"website": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Website"
},
"company_linkedin": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Linkedin"
},
"linkedin": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Linkedin"
},
"country": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Country"
},
"siren": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Siren"
},
"siret": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Siret"
},
"siret_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Siret Address"
},
"siret_zip": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Siret Zip"
},
"siret_city": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Siret City"
},
"vat": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Vat"
},
"nb_employees": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Nb Employees"
},
"employee_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Employee Count"
},
"naf5_code": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Naf5 Code"
},
"naf5_des": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Naf5 Des"
},
"industry": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Industry"
},
"job": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Job"
},
"job_level": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Job Level"
},
"job_function": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Job Function"
},
"company_turnover": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Turnover"
},
"company_results": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Results"
}
},
"required": [
"success"
],
"title": "EnrichContactOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limit**: ~60 requests/second per the vendor docs.
- **Async enrichment**: requests are processed asynchronously; the tool
polls every 5 seconds for up to 2 minutes before giving up.
- **Pay on success**: a credit is consumed only when a verified email
is returned — no charge when no email is found.
- **Error model**: non-2xx responses, an API error flag, timeouts, and
an expired polling window are caught and returned as `success=False`
+ `error` rather than raising. Plan retries on the agent side based on
the error string.
## Related integrations
## Links
- [Dropcontact](https://www.dropcontact.com)
---
# ElevenLabs Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/elevenlabs
AI voice generation, transcription, sound effects, voice cloning, and conversational AI agents. Uses the `elevenlabs` SDK.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/elevenlabs/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **ElevenLabs** to any ModuleX agent or workflow. AI voice integration via the **synchronous** `elevenlabs` SDK. 15 actions across TTS, STT, sound effects, voice library / cloning / isolation, subscription, and Conversational-AI agents.
**Categories**: AI & Machine Learning · Audio · Voice · **Auth**: API Key, ModuleX Managed Key · **Actions**: 15
## Authentication
### API Key Authentication
Authenticate using your ElevenLabs API key
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| ElevenLabs API Key | Your ElevenLabs API key | Yes | `sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
### ModuleX Managed Key
Use ModuleX's managed API keys with usage tracked against your weekly credit limit
## Available Actions
### Parameters
Text to synthesize
Voice ID
Voice name (alternative to voice_id)
TTS model ID (Default: `eleven_multilingual_v2`)
Voice stability (0-1) (Default: `0.5`)
Voice similarity to original (0-1) (Default: `0.75`)
Style exaggeration (0-1) (Default: `0`)
Speech speed (0.7-1.2) (Default: `1`)
ISO 639-1 language code (Default: `en`)
Audio output format (Default: `mp3_44100_128`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"audio_base64": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Audio Base64"
},
"voice": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Voice"
},
"model_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Model Id"
},
"format": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Format"
},
"text_length": {
"default": 0,
"title": "Text Length",
"type": "integer"
},
"audio_size_bytes": {
"default": 0,
"title": "Audio Size Bytes",
"type": "integer"
}
},
"required": [
"success"
],
"title": "TextToSpeechOutput",
"type": "object"
}
```
### Parameters
Base64-encoded audio (XOR with audio_url)
URL to audio file
ISO 639-3 language code
Identify speakers (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"transcript": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Transcript"
},
"diarized": {
"default": false,
"title": "Diarized",
"type": "boolean"
},
"language_detected": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Language Detected"
}
},
"required": [
"success"
],
"title": "SpeechToTextOutput",
"type": "object"
}
```
### Parameters
Sound description (e.g. 'thunder rumbling')
Duration (0.5-5 seconds) (Default: `2`)
Audio output format (Default: `mp3_44100_128`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"audio_base64": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Audio Base64"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"duration_seconds": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Duration Seconds"
},
"format": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Format"
},
"audio_size_bytes": {
"default": 0,
"title": "Audio Size Bytes",
"type": "integer"
}
},
"required": [
"success"
],
"title": "TextToSoundEffectsOutput",
"type": "object"
}
```
### Parameters
Search term to filter voices
created_at_unix or name (Default: `name`)
asc or desc (Default: `desc`)
### Response
```json
{
"$defs": {
"VoiceEntry": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"category": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Category"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"labels": {
"additionalProperties": true,
"title": "Labels",
"type": "object"
}
},
"title": "VoiceEntry",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"voices": {
"items": {
"$ref": "#/$defs/VoiceEntry"
},
"title": "Voices",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "SearchVoicesOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"ModelEntry": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"languages": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Languages",
"type": "array"
}
},
"title": "ModelEntry",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"models": {
"items": {
"$ref": "#/$defs/ModelEntry"
},
"title": "Models",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListModelsOutput",
"type": "object"
}
```
### Parameters
Voice ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"category": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Category"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"labels": {
"additionalProperties": true,
"title": "Labels",
"type": "object"
},
"fine_tuning_status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Fine Tuning Status"
},
"settings": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Settings"
}
},
"required": [
"success"
],
"title": "GetVoiceOutput",
"type": "object"
}
```
### Parameters
Voice name
Base64-encoded audio samples
Optional voice description
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"category": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Category"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
}
},
"required": [
"success"
],
"title": "VoiceCloneOutput",
"type": "object"
}
```
### Parameters
Base64-encoded audio
Audio URL (alternative to base64)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"audio_base64": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Audio Base64"
},
"original_size_bytes": {
"default": 0,
"title": "Original Size Bytes",
"type": "integer"
},
"isolated_size_bytes": {
"default": 0,
"title": "Isolated Size Bytes",
"type": "integer"
}
},
"required": [
"success"
],
"title": "IsolateAudioOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"tier": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Tier"
},
"character_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Character Count"
},
"character_limit": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Character Limit"
},
"can_extend_character_limit": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Extend Character Limit"
},
"allowed_to_extend_character_limit": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Allowed To Extend Character Limit"
},
"next_character_count_reset_unix": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Character Count Reset Unix"
},
"voice_limit": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Voice Limit"
},
"professional_voice_limit": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Professional Voice Limit"
}
},
"required": [
"success"
],
"title": "CheckSubscriptionOutput",
"type": "object"
}
```
### Parameters
Agent name
Greeting message
System prompt
Voice ID (Default: `cgSgspJ2msm6clMCkdW9`)
ISO 639-1 (Default: `en`)
LLM to power the agent (Default: `gemini-2.0-flash-001`)
LLM temperature (Default: `0.5`)
Max LLM tokens
Voice stability (Default: `0.5`)
Voice similarity (Default: `0.8`)
Max conversation duration (Default: `300`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"agent_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Agent Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"voice_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Voice Id"
},
"language": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Language"
},
"llm": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Llm"
}
},
"required": [
"success"
],
"title": "CreateAgentOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"agents": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Agents",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListAgentsOutput",
"type": "object"
}
```
### Parameters
Agent ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"agent_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Agent Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"voice_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Voice Id"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
}
},
"required": [
"success"
],
"title": "GetAgentOutput",
"type": "object"
}
```
### Parameters
Agent ID
Display name for the KB document
Source URL (XOR text / file)
Raw text content
Base64 file (epub / pdf / docx / txt / html)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"knowledge_base_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Knowledge Base Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"agent_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Agent Id"
},
"source_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Source Type"
}
},
"required": [
"success"
],
"title": "AddKnowledgeBaseOutput",
"type": "object"
}
```
### Parameters
Filter by agent ID
Results per page (1-100) (Default: `30`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"conversations": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Conversations",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListConversationsOutput",
"type": "object"
}
```
### Parameters
Conversation ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"conversation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Conversation Id"
},
"agent_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Agent Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"transcript": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Transcript"
},
"message_count": {
"default": 0,
"title": "Message Count",
"type": "integer"
},
"duration_seconds": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Duration Seconds"
},
"analysis_summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Analysis Summary"
}
},
"required": [
"success"
],
"title": "GetConversationOutput",
"type": "object"
}
```
## Related integrations
## Links
- [ElevenLabs](https://elevenlabs.io)
---
# Enrow Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/enrow
Find verified B2B email addresses from a full name and company, or verify the deliverability of an existing email. Enrow performs deterministic verifications including catch-all emails — no additional verifier needed.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/enrow/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Enrow** to any ModuleX agent or workflow. Find and verify B2B email addresses with triple-verified accuracy against the Enrow REST API (`api.enrow.io`). Resolve a professional email from a full name and company, or check the deliverability of an existing address — including deterministic handling of catch-all domains.
**Categories**: Sales · Enrichment · Sales Engagement · **Auth**: API Key · **Actions**: 2
## Authentication
### API Key Authentication
Authenticate using your Enrow API key
Sign in to your Enrow account at https://enrow.io
Open the Integrations section of your account settings
Copy your API key (or create a new one)
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Enrow API Key | Your Enrow API key from the Integrations section | Yes | `-` |
## Available Actions
### Parameters
Full name of the person (e.g. "John Doe")
Company domain (e.g. "apple.com"). Preferred over company_name. Provide company_domain or company_name.
Company name (e.g. "Apple"). Used when the company domain is unavailable. Provide company_domain or company_name.
### Response
```json
{
"additionalProperties": false,
"description": "Result of an Enrow find-email search (submit + poll).",
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"qualification": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Qualification"
},
"fullname": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Fullname"
},
"company_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Name"
},
"company_domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Domain"
},
"linkedin_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Linkedin Url"
}
},
"required": [
"success"
],
"title": "FindEmailOutput",
"type": "object"
}
```
### Parameters
Email address to verify (e.g. "john@example.com")
### Response
```json
{
"additionalProperties": false,
"description": "Result of an Enrow verify-email check (submit + poll).",
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"qualification": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Qualification"
}
},
"required": [
"success"
],
"title": "VerifyEmailOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limit**: roughly ~50 requests/second; keep bursts modest,
especially during result polling.
- **Pricing** (approx., per the Enrow Starter plan): `find_email`
charges 1 credit per valid email found; `verify_email` charges
0.25 credits per verification.
- **Error model**: non-2xx responses, request timeouts, and an
expired polling window are caught and returned as `success=False`
+ `error` rather than raising. Plan retries on the agent side based
on the error string.
## Related integrations
## Links
- [Enrow](https://enrow.io)
---
# Etsy Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/etsy
Etsy marketplace listing management via the Open API v3
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/etsy/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Etsy** to any ModuleX agent or workflow. Manage Etsy marketplace listings, inventory, and properties via the Etsy Open API v3 (`openapi.etsy.com/v3`).
**Categories**: E-Commerce · Marketplace · **Auth**: OAuth2 · **Actions**: 6
## Authentication
### OAuth2 Authentication
Connect using Etsy OAuth2 (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Etsy OAuth App Client ID (API Key) | Yes | `xxxxxxxxxxxxxxxxxxxxxxxx` |
| Client Secret | Etsy OAuth App Client Secret | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://www.etsy.com/oauth/connect`
- **Token URL**: `https://api.etsy.com/v3/public/oauth/token`
- **Scopes**: `listings_r`, `listings_w`, `listings_d`, `transactions_r`, `shops_r`
## Available Actions
### Parameters
The positive non-zero number of products available for purchase
The listing's title string
A description of the product for sale in the listing
The positive non-zero price of the product as a decimal string (e.g. '29.99')
Who made the product: i_did, collective, someone_else
Era when product was made: made_to_order, 2020_2023, 2010_2019, 2004_2009, before_2004, 2000_2003, 1990s, 1980s, 1970s, 1960s, 1950s, 1940s, 1930s, 1920s, 1910s, 1900s, 1800s, 1700s, before_1700
The numerical taxonomy ID of the listing
When true, tags the listing as a supply product; otherwise a finished product
Listing type: physical, download, both
The numeric ID of the shipping profile. Required when listing type is physical.
### Response
```json
{
"$defs": {
"ListingResource": {
"additionalProperties": false,
"properties": {
"listing_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Listing Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"quantity": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Quantity"
},
"price": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Price"
},
"who_made": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Who Made"
},
"when_made": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "When Made"
},
"taxonomy_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Taxonomy Id"
},
"is_supply": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Supply"
},
"listing_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Listing Type"
},
"views": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Views"
},
"num_favorers": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Num Favorers"
},
"shipping_profile_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Shipping Profile Id"
}
},
"title": "ListingResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"listing": {
"anyOf": [
{
"$ref": "#/$defs/ListingResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateDraftListingProductOutput",
"type": "object"
}
```
### Parameters
The ID of the listing to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"listing_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Listing Id"
}
},
"required": [
"success"
],
"title": "DeleteListingOutput",
"type": "object"
}
```
### Parameters
The ID of the listing to retrieve
### Response
```json
{
"$defs": {
"ListingResource": {
"additionalProperties": false,
"properties": {
"listing_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Listing Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"quantity": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Quantity"
},
"price": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Price"
},
"who_made": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Who Made"
},
"when_made": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "When Made"
},
"taxonomy_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Taxonomy Id"
},
"is_supply": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Supply"
},
"listing_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Listing Type"
},
"views": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Views"
},
"num_favorers": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Num Favorers"
},
"shipping_profile_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Shipping Profile Id"
}
},
"title": "ListingResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"listing": {
"anyOf": [
{
"$ref": "#/$defs/ListingResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetListingOutput",
"type": "object"
}
```
### Parameters
The ID of the listing whose inventory to retrieve
### Response
```json
{
"$defs": {
"InventoryProduct": {
"additionalProperties": false,
"properties": {
"product_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Product Id"
},
"sku": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sku"
},
"property_values": {
"items": {
"$ref": "#/$defs/PropertyValue"
},
"title": "Property Values",
"type": "array"
},
"offerings": {
"items": {
"$ref": "#/$defs/Offering"
},
"title": "Offerings",
"type": "array"
}
},
"title": "InventoryProduct",
"type": "object"
},
"Offering": {
"additionalProperties": false,
"properties": {
"offering_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Offering Id"
},
"price": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Price"
},
"quantity": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Quantity"
},
"is_enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Enabled"
}
},
"title": "Offering",
"type": "object"
},
"PropertyValue": {
"additionalProperties": false,
"properties": {
"property_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Property Id"
},
"property_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Property Name"
},
"value_ids": {
"items": {
"type": "integer"
},
"title": "Value Ids",
"type": "array"
},
"values": {
"items": {
"type": "string"
},
"title": "Values",
"type": "array"
}
},
"title": "PropertyValue",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"products": {
"items": {
"$ref": "#/$defs/InventoryProduct"
},
"title": "Products",
"type": "array"
},
"price_on_property": {
"items": {
"type": "integer"
},
"title": "Price On Property",
"type": "array"
},
"quantity_on_property": {
"items": {
"type": "integer"
},
"title": "Quantity On Property",
"type": "array"
},
"sku_on_property": {
"items": {
"type": "integer"
},
"title": "Sku On Property",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetListingInventoryOutput",
"type": "object"
}
```
### Parameters
The ID of the listing whose inventory to update
JSON array of product objects containing sku, property_values, and offerings
List of listing property ID integers for properties that change product prices
List of listing property ID integers for properties that change product quantity
List of listing property ID integers for properties that change the product SKU
### Response
```json
{
"$defs": {
"InventoryProduct": {
"additionalProperties": false,
"properties": {
"product_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Product Id"
},
"sku": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sku"
},
"property_values": {
"items": {
"$ref": "#/$defs/PropertyValue"
},
"title": "Property Values",
"type": "array"
},
"offerings": {
"items": {
"$ref": "#/$defs/Offering"
},
"title": "Offerings",
"type": "array"
}
},
"title": "InventoryProduct",
"type": "object"
},
"Offering": {
"additionalProperties": false,
"properties": {
"offering_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Offering Id"
},
"price": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Price"
},
"quantity": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Quantity"
},
"is_enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Enabled"
}
},
"title": "Offering",
"type": "object"
},
"PropertyValue": {
"additionalProperties": false,
"properties": {
"property_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Property Id"
},
"property_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Property Name"
},
"value_ids": {
"items": {
"type": "integer"
},
"title": "Value Ids",
"type": "array"
},
"values": {
"items": {
"type": "string"
},
"title": "Values",
"type": "array"
}
},
"title": "PropertyValue",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"products": {
"items": {
"$ref": "#/$defs/InventoryProduct"
},
"title": "Products",
"type": "array"
},
"price_on_property": {
"items": {
"type": "integer"
},
"title": "Price On Property",
"type": "array"
},
"quantity_on_property": {
"items": {
"type": "integer"
},
"title": "Quantity On Property",
"type": "array"
},
"sku_on_property": {
"items": {
"type": "integer"
},
"title": "Sku On Property",
"type": "array"
}
},
"required": [
"success"
],
"title": "UpdateListingInventoryOutput",
"type": "object"
}
```
### Parameters
The ID of the listing
The ID of the property to update
Array of integer value IDs for the property
Array of string value labels for the property (e.g. 'Black', 'Christmas')
### Response
```json
{
"$defs": {
"ListingProperty": {
"additionalProperties": false,
"properties": {
"property_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Property Id"
},
"property_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Property Name"
},
"scale_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Scale Id"
},
"value_ids": {
"items": {
"type": "integer"
},
"title": "Value Ids",
"type": "array"
},
"values": {
"items": {
"type": "string"
},
"title": "Values",
"type": "array"
}
},
"title": "ListingProperty",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"listing_property": {
"anyOf": [
{
"$ref": "#/$defs/ListingProperty"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UpdateListingPropertyOutput",
"type": "object"
}
```
## Limits & Quotas
- Etsy Open API v3 rate limit: 10,000 requests per day per API key.
- Burst limit: approximately 10 requests per second.
- Error model: non-2xx responses raise `httpx.HTTPStatusError` (Pattern A). The agent should retry on 429/5xx.
## Related integrations
## Links
- [Etsy](https://www.etsy.com)
---
# Exa Search Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/exa-search
AI-powered semantic search engine for intelligent web search, content extraction, similarity matching, and answer generation
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/exa/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Exa Search** to any ModuleX agent or workflow. AI-powered semantic web search, content extraction, similarity matching, and answer generation against the Exa REST API (`api.exa.ai`).
**Categories**: Web Search & Scraping · Data · Search · **Auth**: API Key, ModuleX Managed Key · **Actions**: 4
## Authentication
### API Key Authentication
Authenticate using your Exa API key
Go to https://dashboard.exa.ai and sign up or log in
Navigate to 'API Keys' section
Create a new API key or copy your existing one
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Exa API Key | Your Exa API key from dashboard.exa.ai | Yes | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
### ModuleX Managed Key
Use ModuleX's managed API keys with usage tracked against your weekly credit limit
## Available Actions
### Parameters
Search query string
Number of results to return (1-100) (Default: `10`)
Search type: 'auto' (default), 'neural', 'deep', or 'fast' (Default: `auto`)
Filter results by content category
List of domains to include in search results
List of domains to exclude from search results
Filter results published after this date (ISO 8601 format)
Filter results published before this date (ISO 8601 format)
Whether to include page text content in results (Default: `true`)
Whether to include relevant text highlights (Default: `false`)
Whether to include AI-generated summaries (Default: `false`)
### Response
```json
{
"$defs": {
"SearchResultItem": {
"additionalProperties": false,
"description": "A single result row in ``search``.",
"properties": {
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"published_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Published Date"
},
"author": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Author"
},
"score": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Score"
},
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
},
"highlights": {
"items": {
"type": "string"
},
"title": "Highlights",
"type": "array"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
}
},
"title": "SearchResultItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"results": {
"items": {
"$ref": "#/$defs/SearchResultItem"
},
"title": "Results",
"type": "array"
},
"total_results": {
"default": 0,
"title": "Total Results",
"type": "integer"
},
"search_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Search Type"
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Request Id"
}
},
"required": [
"success"
],
"title": "SearchOutput",
"type": "object"
}
```
### Parameters
List of URLs to extract content from
Whether to include full page text (Default: `true`)
Whether to include relevant text highlights (Default: `false`)
Number of highlight snippets per URL (Default: `3`)
Whether to include AI-generated summary (Default: `false`)
Live crawl option: 'never', 'fallback', 'preferred', 'always' (Default: `fallback`)
### Response
```json
{
"$defs": {
"ContentItem": {
"additionalProperties": false,
"description": "A single result row in ``get_contents``.",
"properties": {
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"published_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Published Date"
},
"author": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Author"
},
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
},
"highlights": {
"items": {
"type": "string"
},
"title": "Highlights",
"type": "array"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
}
},
"title": "ContentItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"results": {
"items": {
"$ref": "#/$defs/ContentItem"
},
"title": "Results",
"type": "array"
},
"total_results": {
"default": 0,
"title": "Total Results",
"type": "integer"
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Request Id"
}
},
"required": [
"success"
],
"title": "GetContentsOutput",
"type": "object"
}
```
### Parameters
URL to find similar pages for
Number of similar results to return (1-100) (Default: `10`)
List of domains to include in results
List of domains to exclude from results
Whether to exclude results from the source URL's domain (Default: `true`)
Filter by content category
Include page text content in results (Default: `true`)
### Response
```json
{
"$defs": {
"SimilarResultItem": {
"additionalProperties": false,
"description": "A single result row in ``find_similar``.",
"properties": {
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"published_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Published Date"
},
"author": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Author"
},
"score": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Score"
},
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
}
},
"title": "SimilarResultItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"source_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Source Url"
},
"results": {
"items": {
"$ref": "#/$defs/SimilarResultItem"
},
"title": "Results",
"type": "array"
},
"total_results": {
"default": 0,
"title": "Total Results",
"type": "integer"
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Request Id"
}
},
"required": [
"success"
],
"title": "FindSimilarOutput",
"type": "object"
}
```
### Parameters
Question to answer using web search
Number of search results to use for generating answer (Default: `5`)
Search type for finding sources (Default: `auto`)
Domains to prioritize for answers
Domains to exclude from answer sources
### Response
```json
{
"$defs": {
"AnswerSource": {
"additionalProperties": false,
"description": "A single citation in ``answer``'s sources list.",
"properties": {
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"published_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Published Date"
}
},
"title": "AnswerSource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"answer": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Answer"
},
"sources": {
"items": {
"$ref": "#/$defs/AnswerSource"
},
"title": "Sources",
"type": "array"
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Request Id"
}
},
"required": [
"success"
],
"title": "AnswerOutput",
"type": "object"
}
```
## Limits & Quotas
- **Standard tier**: ~60 req/min.
- **Deep search**: ~20 req/min (higher compute cost).
- **Pricing** (approx., per legacy manifest):
- Neural search 1–25 results: $0.005
- Neural search 26–100: $0.025
- Deep search 1–25: $0.015
- Deep search 26–100: $0.075
- Content per page: $0.001
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising. Plan for
retries on the agent side based on the error string.
## Related integrations
## Links
- [Exa Search](https://exa.ai)
---
# fal.ai Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/fal-ai
Queue-based AI model inference via the fal.ai platform
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/fal_ai/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **fal.ai** to any ModuleX agent or workflow. Queue-based AI model inference via the fal.ai platform API (`queue.fal.run/fal-ai`). Submit requests to run generative AI models asynchronously, monitor their status, retrieve results, and cancel pending tasks.
**Categories**: AI & Machine Learning · Generative AI · **Auth**: API Key · **Actions**: 4
## Authentication
### API Key Authentication
Authenticate using your fal.ai API key
Go to https://fal.ai/dashboard/keys and sign in
Create a new API key or copy your existing one
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| fal.ai API Key | Your fal.ai API key from https://fal.ai/dashboard/keys | Yes | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
The unique identifier for the fal.ai app/model (e.g. 'lora', 'fast-sdxl')
Input data for the model. Fields depend on the specific app/model being called
Optional URL to receive webhook updates about the request status
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Request Id"
},
"response_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Response Url"
},
"status_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status Url"
},
"cancel_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cancel Url"
}
},
"required": [
"success"
],
"title": "AddRequestToQueueOutput",
"type": "object"
}
```
### Parameters
The unique identifier for the fal.ai app/model
The unique identifier for the request to cancel
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "CancelRequestOutput",
"type": "object"
}
```
### Parameters
The unique identifier for the fal.ai app/model
The unique identifier for the request
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetRequestResponseOutput",
"type": "object"
}
```
### Parameters
The unique identifier for the fal.ai app/model
The unique identifier for the request
Whether to include logs in the status response
### Response
```json
{
"$defs": {
"LogEntry": {
"additionalProperties": false,
"description": "A log entry from a queued request's status.",
"properties": {
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"level": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Level"
},
"timestamp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp"
}
},
"title": "LogEntry",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"queue_position": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Queue Position"
},
"logs": {
"items": {
"$ref": "#/$defs/LogEntry"
},
"title": "Logs",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetRequestStatusOutput",
"type": "object"
}
```
## Limits & Quotas
- Rate limits depend on your fal.ai plan tier (free tier has limited concurrent requests).
- Requests are queued; queue position is returned in status responses.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [fal.ai](https://fal.ai)
---
# Fellow Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/fellow
Meeting productivity platform for notes, action items, and meeting management
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/fellow/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Fellow** to any ModuleX agent or workflow. Meeting productivity platform for notes, action items, and meeting management via the Fellow REST API (`https://.fellow.app/api/v1`).
**Categories**: Productivity & Collaboration · Meetings · **Auth**: API Key · **Actions**: 3
## Authentication
### API Key Authentication
Authenticate using your Fellow API key and workspace subdomain
Sign in to your Fellow workspace at https://<subdomain>.fellow.app
Navigate to Settings > Integrations > API
Generate a new API key or copy your existing one
Note your workspace subdomain (the part before .fellow.app in your URL)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Workspace Subdomain | Your Fellow workspace subdomain (the part before .fellow.app) | Yes | `mycompany` |
| API Key | Your Fellow API key from Settings > Integrations > API | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
The ID of the action item to archive
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "ArchiveActionItemOutput",
"type": "object"
}
```
### Parameters
The ID of the action item to mark as complete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CompleteActionItemOutput",
"type": "object"
}
```
### Parameters
The ID of the note to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetNoteByIdOutput",
"type": "object"
}
```
## Limits & Quotas
- No documented public rate limits from Fellow's API documentation.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Fellow](https://fellow.ai)
---
# Figma Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/figma
Design collaboration platform for creating, sharing, and commenting on design files
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/figma/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Figma** to any ModuleX agent or workflow. Design collaboration platform for creating, sharing, and commenting on design files via the Figma REST API (`api.figma.com`).
**Categories**: Productivity & Collaboration · Design · **Auth**: OAuth2 · **Actions**: 3
## Authentication
### OAuth2 Authentication
Connect using Figma OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Figma OAuth App Client ID | Yes | `-` |
| Client Secret | Figma OAuth App Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://www.figma.com/oauth`
- **Token URL**: `https://api.figma.com/v1/oauth/token`
- **Scopes**: `file_content:read`, `file_comments:read`, `file_comments:write`
## Available Actions
### Parameters
The Figma file ID (found in the file URL after /file/)
### Response
```json
{
"$defs": {
"CommentUser": {
"additionalProperties": false,
"description": "A Figma user who authored a comment.",
"properties": {
"handle": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Handle"
},
"img_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Img Url"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
}
},
"title": "CommentUser",
"type": "object"
},
"FigmaComment": {
"additionalProperties": false,
"description": "A single comment on a Figma file.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"file_key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "File Key"
},
"parent_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Parent Id"
},
"user": {
"anyOf": [
{
"$ref": "#/$defs/CommentUser"
},
{
"type": "null"
}
],
"default": null
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"resolved_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Resolved At"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Order Id"
}
},
"title": "FigmaComment",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"comments": {
"items": {
"$ref": "#/$defs/FigmaComment"
},
"title": "Comments",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListCommentsOutput",
"type": "object"
}
```
### Parameters
The Figma file ID (found in the file URL after /file/)
The ID of the comment to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "DeleteCommentOutput",
"type": "object"
}
```
### Parameters
The Figma file ID (found in the file URL after /file/)
The text contents of the comment to post
The ID of the comment to reply to (must be a root comment)
### Response
```json
{
"$defs": {
"CommentUser": {
"additionalProperties": false,
"description": "A Figma user who authored a comment.",
"properties": {
"handle": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Handle"
},
"img_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Img Url"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
}
},
"title": "CommentUser",
"type": "object"
},
"FigmaComment": {
"additionalProperties": false,
"description": "A single comment on a Figma file.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"file_key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "File Key"
},
"parent_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Parent Id"
},
"user": {
"anyOf": [
{
"$ref": "#/$defs/CommentUser"
},
{
"type": "null"
}
],
"default": null
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"resolved_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Resolved At"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Order Id"
}
},
"title": "FigmaComment",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"comment": {
"anyOf": [
{
"$ref": "#/$defs/FigmaComment"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "PostACommentOutput",
"type": "object"
}
```
## Limits & Quotas
- Figma REST API rate limit: 30 requests per minute per OAuth token (may vary by endpoint and plan).
- No per-request billing; API access is included with Figma Professional and above.
- Error model: non-2xx responses are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Figma](https://www.figma.com)
---
# Findymail Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/findymail
Find verified work emails by name, domain, or LinkedIn URL, verify deliverability, reverse-lookup profiles from emails, enrich company data, find employees by job title, look up phone numbers, search technology stacks, and check credit usage.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/findymail/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Findymail** to any ModuleX agent or workflow. Find and verify B2B emails, phones, employees, and company data against the Findymail REST API (`app.findymail.com`).
**Categories**: Sales · Enrichment · Sales Engagement · **Auth**: API Key · **Actions**: 11
## Authentication
### API Key Authentication
Authenticate using your Findymail API key
Sign in at https://app.findymail.com
Open the API page in your dashboard
Copy your API key
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Findymail API Key | Your Findymail API key from the dashboard API page | Yes | `-` |
## Available Actions
### Parameters
Person's full name (e.g., 'John Doe')
Company domain (preferred) or company name (e.g., stripe.com)
### Response
```json
{
"$defs": {
"Contact": {
"additionalProperties": false,
"description": "A contact discovered by an email-finder action.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Domain"
}
},
"title": "Contact",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"contact": {
"anyOf": [
{
"$ref": "#/$defs/Contact"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "FindEmailFromNameOutput",
"type": "object"
}
```
### Parameters
Person's LinkedIn URL or username (e.g., 'https://linkedin.com/in/johndoe' or 'johndoe')
### Response
```json
{
"$defs": {
"Contact": {
"additionalProperties": false,
"description": "A contact discovered by an email-finder action.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Domain"
}
},
"title": "Contact",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"contact": {
"anyOf": [
{
"$ref": "#/$defs/Contact"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "FindEmailFromLinkedinOutput",
"type": "object"
}
```
### Parameters
Company domain (e.g., stripe.com)
Target roles at the company (max 3, e.g., ["CEO", "Founder"])
### Response
```json
{
"$defs": {
"Contact": {
"additionalProperties": false,
"description": "A contact discovered by an email-finder action.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Domain"
}
},
"title": "Contact",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"contacts": {
"items": {
"$ref": "#/$defs/Contact"
},
"title": "Contacts",
"type": "array"
}
},
"required": [
"success"
],
"title": "FindEmailsByDomainOutput",
"type": "object"
}
```
### Parameters
Email address to verify (e.g., john@example.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"verified": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Verified"
},
"provider": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Provider"
}
},
"required": [
"success"
],
"title": "VerifyEmailOutput",
"type": "object"
}
```
### Parameters
Work or personal email address to look up
Whether to return enriched profile metadata (default: false) (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"linkedin_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Linkedin Url"
},
"full_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Full Name"
},
"username": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Username"
},
"headline": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Headline"
},
"job_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Job Title"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"city": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "City"
},
"region": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Region"
},
"country": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Country"
},
"company_linkedin_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Linkedin Url"
},
"company_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Name"
},
"company_website": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Website"
},
"is_premium": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Premium"
},
"is_open_profile": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Open Profile"
},
"skills": {
"items": {},
"title": "Skills",
"type": "array"
},
"jobs": {
"items": {},
"title": "Jobs",
"type": "array"
},
"educations": {
"items": {},
"title": "Educations",
"type": "array"
},
"certificates": {
"items": {},
"title": "Certificates",
"type": "array"
}
},
"required": [
"success"
],
"title": "ReverseEmailLookupOutput",
"type": "object"
}
```
### Parameters
Company LinkedIn URL (e.g., https://www.linkedin.com/company/stripe/)
Company domain (e.g., stripe.com)
Company name (e.g., Stripe)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Domain"
},
"company_size": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Size"
},
"industry": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Industry"
},
"linkedin_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Linkedin Url"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
}
},
"required": [
"success"
],
"title": "GetCompanyOutput",
"type": "object"
}
```
### Parameters
Company website or domain (e.g., google.com)
Target job titles to search for (max 10, e.g., ["Software Engineer", "CEO"])
Number of contacts to return (max 5, default 1)
### Response
```json
{
"$defs": {
"Employee": {
"additionalProperties": false,
"description": "A person returned by ``find_employees``.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"linkedin_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Linkedin Url"
},
"company_website": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Website"
},
"company_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Name"
},
"job_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Job Title"
}
},
"title": "Employee",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"employees": {
"items": {
"$ref": "#/$defs/Employee"
},
"title": "Employees",
"type": "array"
}
},
"required": [
"success"
],
"title": "FindEmployeesOutput",
"type": "object"
}
```
### Parameters
Person's LinkedIn URL or username (e.g., 'https://linkedin.com/in/johndoe' or 'johndoe')
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Phone"
},
"line_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Line Type"
}
},
"required": [
"success"
],
"title": "FindPhoneOutput",
"type": "object"
}
```
### Parameters
Search term (min 2 characters, e.g., "React")
### Response
```json
{
"$defs": {
"Technology": {
"additionalProperties": false,
"description": "A technology returned by the technology endpoints.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"category": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Category"
},
"subcategory": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subcategory"
},
"last_detected_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Detected At"
}
},
"title": "Technology",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"technologies": {
"items": {
"$ref": "#/$defs/Technology"
},
"title": "Technologies",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchTechnologiesOutput",
"type": "object"
}
```
### Parameters
Company domain to look up (e.g., stripe.com)
Filter by technology names, case-insensitive (e.g., ["React", "TypeScript"])
### Response
```json
{
"$defs": {
"Technology": {
"additionalProperties": false,
"description": "A technology returned by the technology endpoints.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"category": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Category"
},
"subcategory": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subcategory"
},
"last_detected_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Detected At"
}
},
"title": "Technology",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Domain"
},
"technologies": {
"items": {
"$ref": "#/$defs/Technology"
},
"title": "Technologies",
"type": "array"
}
},
"required": [
"success"
],
"title": "LookupTechnologiesOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"credits": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Credits"
},
"verifier_credits": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Verifier Credits"
}
},
"required": [
"success"
],
"title": "GetCreditsOutput",
"type": "object"
}
```
## Limits & Quotas
- **Credits**: finder and verifier credits are consumed per successful
lookup (e.g. verify = 1 verifier credit, find email = 1 finder credit on a
match, find phone = 10 finder credits on a match). Use `get_credits` to
check the remaining balance.
- **Rate limits**: `find_emails_by_domain` is limited to 5 concurrent
synchronous requests; `search_technologies` is limited to ~10 requests per
minute.
- **Error model**: non-2xx responses and timeouts are caught and returned as
`success=False` + `error` rather than raising. Plan retries on the agent
side based on the error string.
## Related integrations
## Links
- [Findymail](https://www.findymail.com)
---
# Firecrawl Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/firecrawl
AI-powered web scraping, crawling, and search tool for extracting content from websites with advanced options for JavaScript rendering, caching, and structured data extraction.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/firecrawl/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Firecrawl** to any ModuleX agent or workflow. AI-powered web scraping, crawling, and search against the Firecrawl v1 REST API (`api.firecrawl.dev/v1`). Covers single-URL scraping, URL discovery (map), web search, multi-page crawls with job-id + status polling, LLM-based structured extraction, and batch scraping.
**Categories**: Web Search & Scraping · Data · Search · **Auth**: API Key, ModuleX Managed Key · **Actions**: 7
## Authentication
### API Key Authentication
Authenticate using your Firecrawl API key
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Firecrawl API Key | Your Firecrawl API key for authentication | Yes | `fc-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
### ModuleX Managed Key
Use ModuleX's managed API keys with usage tracked against your weekly credit limit
## Available Actions
### Parameters
The URL to scrape
Content formats: markdown, html, rawHtml, screenshot, links, summary (Default: `["markdown"]`)
Extract only the main content, filtering out navigation/footers (Default: `true`)
HTML tags to specifically include in extraction
HTML tags to exclude from extraction
Time in milliseconds to wait for dynamic content
Use mobile viewport
Remove base64-encoded images from output
Maximum age in milliseconds for cached content. Enables faster scrapes for cached pages.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "ScrapeOutput",
"type": "object"
}
```
### Parameters
Starting URL for URL discovery
Optional search term to filter URLs
Sitemap handling: 'include', 'skip', or 'only'
Include URLs from subdomains in results
Maximum number of URLs to return
Do not return URLs with query parameters (Default: `true`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "MapWebsiteOutput",
"type": "object"
}
```
### Parameters
Search query string (supports operators)
Maximum number of results to return (Default: `5`)
Time-based search filter
Location parameter for search results
Options for scraping search results
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "SearchOutput",
"type": "object"
}
```
### Parameters
Starting URL for the crawl
URL paths to exclude from crawling
Only crawl these URL paths
Maximum depth to crawl relative to the entered URL
Maximum number of pages to crawl (Default: `100`)
Allow crawling links to external domains (Default: `false`)
Allow crawling links to parent paths (Default: `false`)
Ignore the website sitemap when crawling (Default: `false`)
Options for scraping each page
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CrawlOutput",
"type": "object"
}
```
### Parameters
Crawl job ID returned from the crawl action
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CheckCrawlStatusOutput",
"type": "object"
}
```
### Parameters
Array of URLs to extract information from
Custom prompt for the LLM extraction
JSON schema for structured data extraction
Allow extraction from external links (Default: `false`)
Enable web search for additional context (Default: `false`)
Include subdomains in extraction (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "ExtractOutput",
"type": "object"
}
```
### Parameters
Array of URLs to scrape
Content formats to extract (Default: `["markdown"]`)
Extract only the main content (Default: `true`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "BatchScrapeOutput",
"type": "object"
}
```
## Limits & Quotas
- HTTP timeouts: 120s for scrape/map/search/status; 180s for
crawl/extract/batch (long-running jobs).
- Snake_case input parameters are converted to camelCase for the
upstream API (`only_main_content` → `onlyMainContent`, etc.).
- Response `data` carries the upstream JSON body unchanged so callers
see the rich nested metadata Firecrawl returns.
- Failures (non-2xx, timeouts, parse errors) surface as
`success=False` + `error`; empty/blank API keys short-circuit.
## Related integrations
## Links
- [Firecrawl](https://firecrawl.dev)
---
# Freshdesk Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/freshdesk
Customer support helpdesk platform for managing tickets, contacts, agents, and knowledge base articles via the Freshdesk REST API.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/freshdesk/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Freshdesk** to any ModuleX agent or workflow. Customer support helpdesk platform for managing tickets, contacts, agents, and knowledge base articles via the Freshdesk REST API (`{domain}.freshdesk.com/api/v2`).
**Categories**: Customer Support · Helpdesk · Productivity & Collaboration · **Auth**: API Key · **Actions**: 45
## Authentication
### API Key Authentication
Authenticate using your Freshdesk API key and subdomain
Log in to your Freshdesk account
Click your profile picture in the top right corner
Go to Profile Settings
Your API key is displayed on the right side of the page
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Freshdesk Domain | Your Freshdesk subdomain (e.g. 'mycompany' for mycompany.freshdesk.com) | Yes | `mycompany` |
| Freshdesk API Key | Your Freshdesk API key from Profile Settings | Yes | `xXxXxXxXxXxXxXxXxXxX` |
## Available Actions
### Parameters
Subject of the ticket
HTML content of the ticket
Email address of the requester
Priority of the ticket: 1 (Low), 2 (Medium), 3 (High), 4 (Urgent) (Default: `1`)
Status of the ticket: 2 (Open), 3 (Pending), 4 (Resolved), 5 (Closed) (Default: `2`)
ID of the company to associate with the ticket
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateTicketOutput",
"type": "object"
}
```
### Parameters
ID of the ticket to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetTicketOutput",
"type": "object"
}
```
### Parameters
ID of the ticket to update
New subject for the ticket
New HTML content for the ticket
Priority: 1 (Low), 2 (Medium), 3 (High), 4 (Urgent)
Status: 2 (Open), 3 (Pending), 4 (Resolved), 5 (Closed)
ID of the group to assign the ticket to
ID of the agent to assign the ticket to
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "UpdateTicketOutput",
"type": "object"
}
```
### Parameters
Predefined filter: new_and_my_open, watching, spam, deleted, all_tickets
Filter tickets by requester ID
Filter tickets by requester email
Filter tickets by company ID
Maximum number of results to return (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListAllTicketsOutput",
"type": "object"
}
```
### Parameters
ID of the ticket to close
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CloseTicketOutput",
"type": "object"
}
```
### Parameters
ID of the ticket to add a note to
Content of the note in HTML format
Whether the note is private (true) or public (false) (Default: `true`)
List of email addresses to notify about this note
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "AddNoteToTicketOutput",
"type": "object"
}
```
### Parameters
ID of the ticket
List of tag names to add to the ticket
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "AddTicketTagsOutput",
"type": "object"
}
```
### Parameters
ID of the ticket
List of tag names to remove from the ticket
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "RemoveTicketTagsOutput",
"type": "object"
}
```
### Parameters
ID of the ticket
List of tag names to set on the ticket (replaces existing tags)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "SetTicketTagsOutput",
"type": "object"
}
```
### Parameters
ID of the ticket
Priority: 1 (Low), 2 (Medium), 3 (High), 4 (Urgent)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "SetTicketPriorityOutput",
"type": "object"
}
```
### Parameters
ID of the ticket
Status: 2 (Open), 3 (Pending), 4 (Resolved), 5 (Closed)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "SetTicketStatusOutput",
"type": "object"
}
```
### Parameters
ID of the ticket
ID of the agent to assign the ticket to
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "AssignTicketToAgentOutput",
"type": "object"
}
```
### Parameters
ID of the ticket
ID of the group to assign the ticket to
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "AssignTicketToGroupOutput",
"type": "object"
}
```
### Parameters
Email address of the contact
Name of the contact
Phone number of the contact
ID of the company to associate with the contact
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateContactOutput",
"type": "object"
}
```
### Parameters
ID of the contact to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetContactOutput",
"type": "object"
}
```
### Parameters
ID of the contact to update
Updated name of the contact
Updated email address
Updated phone number
ID of the company to associate with the contact
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "UpdateContactOutput",
"type": "object"
}
```
### Parameters
Name of the company
List of domain names associated with the company (e.g. ['example.com'])
Description of the company
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateCompanyOutput",
"type": "object"
}
```
### Parameters
Email address of the agent
Ticket permission: 1 (Global Access), 2 (Group Access), 3 (Restricted Access)
Set to true if this is an occasional agent
Type: 1 (Support Agent), 2 (Field Agent), 3 (Collaborator)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateAgentOutput",
"type": "object"
}
```
### Parameters
ID of the agent to update
Updated email address
Ticket permission: 1 (Global Access), 2 (Group Access), 3 (Restricted Access)
Set to true if this is an occasional agent
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "UpdateAgentOutput",
"type": "object"
}
```
### Parameters
ID of the agent to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetAgentOutput",
"type": "object"
}
```
### Parameters
Filter agents by email address
Filter by state: fulltime, occasional
Maximum number of results to return (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListAgentsOutput",
"type": "object"
}
```
### Parameters
ID of the ticket to reply to
Content of the reply in HTML format
List of email addresses to CC
List of email addresses to BCC
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateReplyOutput",
"type": "object"
}
```
### Parameters
ID of the ticket to forward
Content of the forward in HTML format
List of email addresses to forward to
List of email addresses to CC
List of email addresses to BCC
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "ForwardTicketOutput",
"type": "object"
}
```
### Parameters
ID of the ticket
Content of the reply in HTML format
List of email addresses to reply to
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "ReplyToForwardOutput",
"type": "object"
}
```
### Parameters
ID of the ticket to create the thread for
Type of thread: forward, discussion
ID of the email config to use for the thread
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateThreadOutput",
"type": "object"
}
```
### Parameters
ID of the ticket
ID of the thread to post the message in
Content of the message in HTML format
Subject of the email
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateMessageForThreadOutput",
"type": "object"
}
```
### Parameters
ID of the ticket
Maximum number of results to return (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListTicketConversationsOutput",
"type": "object"
}
```
### Parameters
Maximum number of results to return (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListTicketFieldsOutput",
"type": "object"
}
```
### Parameters
Display name of the ticket field
Label for the field as seen by customers
Field type: custom_dropdown, custom_checkbox, custom_text, custom_paragraph, custom_number, custom_date, custom_decimal, custom_url
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateTicketFieldOutput",
"type": "object"
}
```
### Parameters
ID of the ticket field to update
Updated display name
Updated label for customers
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "UpdateTicketFieldOutput",
"type": "object"
}
```
### Parameters
ID of the folder to create the article in
Title of the article
HTML content of the article
Status: 1 (Draft), 2 (Published)
List of tags for the article
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateSolutionArticleOutput",
"type": "object"
}
```
### Parameters
ID of the article to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetSolutionArticleOutput",
"type": "object"
}
```
### Parameters
ID of the article to update
Updated title
Updated HTML content
Status: 1 (Draft), 2 (Published)
Updated tags for the article
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "UpdateSolutionArticleOutput",
"type": "object"
}
```
### Parameters
ID of the article to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "DeleteSolutionArticleOutput",
"type": "object"
}
```
### Parameters
Search keyword to find matching articles
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchSolutionArticleOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListSolutionCategoriesOutput",
"type": "object"
}
```
### Parameters
ID of the solution category
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListCategoryFoldersOutput",
"type": "object"
}
```
### Parameters
ID of the solution folder
Maximum number of results to return (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListFolderArticlesOutput",
"type": "object"
}
```
### Parameters
Maximum number of results to return (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListAllFoldersOutput",
"type": "object"
}
```
### Parameters
ID of the canned response folder
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListFolderCannedResponsesOutput",
"type": "object"
}
```
### Parameters
ID of the canned response
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetCannedResponseOutput",
"type": "object"
}
```
### Parameters
ID of the canned response folder
Maximum number of results to return (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetFolderCannedResponsesOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListCompaniesOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListEmailConfigsOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListRolesOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limits**: Freshdesk applies per-plan rate limits. Free plans: 50 calls/min. Growth and above: 200-400+ calls/min depending on plan.
- **Pagination**: List endpoints return up to 100 results per page by default.
- **Error model**: non-2xx responses are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Freshdesk](https://freshdesk.com)
---
# Gamma Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/gamma
Integrate Gamma into the workflow. Can generate presentations, documents, webpages, and social posts from text, create from templates, check generation status, and browse themes and folders.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/gamma/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Gamma** to any ModuleX agent or workflow. Generate presentations, documents, webpages, and social posts with AI from text, create from templates, check generation status, and browse workspace themes and folders against the Gamma REST API (`public-api.gamma.app`).
**Categories**: Marketing & Advertising · Document Processing · Content Management · **Auth**: API Key · **Actions**: 5
## Authentication
### API Key Authentication
Authenticate using your Gamma API key
Sign in to Gamma with a Pro, Ultra, Teams, or Business plan
Open Account Settings and navigate to the 'API Keys' section
Create a new API key (format: sk-gamma-xxxxxxxx) or copy an existing one
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Gamma API Key | Your Gamma API key from Account Settings > API Keys | Yes | `sk-gamma-xxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
Text and image URLs used to generate your gamma (1-100,000 tokens)
How to handle input text: generate (AI expands), condense (AI summarizes), or preserve (keep as-is)
Output format: presentation, document, webpage, or social (default: presentation)
Custom Gamma workspace theme ID (use list_themes to find themes)
Number of cards/slides to generate (1-60 for Pro, 1-75 for Ultra; default: 10)
How to split content into cards: auto or inputTextBreaks
Card aspect ratio. Presentation: fluid, 16x9, 4x3. Document: fluid, pageless, letter, a4. Social: 1x1, 4x5, 9x16
Additional instructions for the AI generation (max 2000 chars)
Automatically export the generated gamma as pdf or pptx
Comma-separated folder IDs to store the generated gamma in
Amount of text per card: brief, medium, detailed, or extensive
Tone of the generated text, e.g. "professional" (max 500 chars)
Target audience, e.g. "executives", "students" (max 500 chars)
Language code for the generated text (default: en)
Where to source images: aiGenerated, pictographic, unsplash, webAllImages, webFreeToUse, webFreeToUseCommercially, giphy, placeholder, or noImages
AI image generation model to use when image_source is aiGenerated
Style directive for AI-generated images, e.g. "watercolor"
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"generation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Generation Id"
},
"warnings": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Warnings"
}
},
"required": [
"success"
],
"title": "GenerateOutput",
"type": "object"
}
```
### Parameters
The ID of the template gamma to adapt
Instructions for how to adapt the template (1-100,000 tokens)
Custom Gamma workspace theme ID to apply
Automatically export the generated gamma as pdf or pptx
Comma-separated folder IDs to store the generated gamma in
AI image generation model to use when image_source is aiGenerated
Style directive for AI-generated images, e.g. "watercolor"
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"generation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Generation Id"
},
"warnings": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Warnings"
}
},
"required": [
"success"
],
"title": "GenerateFromTemplateOutput",
"type": "object"
}
```
### Parameters
The generation ID returned by generate or generate_from_template
### Response
```json
{
"$defs": {
"GammaCredits": {
"additionalProperties": false,
"description": "Credit usage reported on a completed generation.",
"properties": {
"deducted": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Deducted"
},
"remaining": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Remaining"
}
},
"title": "GammaCredits",
"type": "object"
},
"GammaError": {
"additionalProperties": false,
"description": "Error details reported on a failed generation.",
"properties": {
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"status_code": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Status Code"
}
},
"title": "GammaError",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"generation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Generation Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"gamma_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Gamma Url"
},
"gamma_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Gamma Id"
},
"export_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Export Url"
},
"credits": {
"anyOf": [
{
"$ref": "#/$defs/GammaCredits"
},
{
"type": "null"
}
],
"default": null
},
"generation_error": {
"anyOf": [
{
"$ref": "#/$defs/GammaError"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CheckStatusOutput",
"type": "object"
}
```
### Parameters
Search query to filter themes by name (case-insensitive)
Maximum number of themes to return per page (max 50)
Pagination cursor from a previous response (next_cursor)
### Response
```json
{
"$defs": {
"ThemeItem": {
"additionalProperties": false,
"description": "A single theme in ``list_themes``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"color_keywords": {
"items": {
"type": "string"
},
"title": "Color Keywords",
"type": "array"
},
"tone_keywords": {
"items": {
"type": "string"
},
"title": "Tone Keywords",
"type": "array"
}
},
"title": "ThemeItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"themes": {
"items": {
"$ref": "#/$defs/ThemeItem"
},
"title": "Themes",
"type": "array"
},
"has_more": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has More"
},
"next_cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Cursor"
}
},
"required": [
"success"
],
"title": "ListThemesOutput",
"type": "object"
}
```
### Parameters
Search query to filter folders by name (case-sensitive)
Maximum number of folders to return per page (max 50)
Pagination cursor from a previous response (next_cursor)
### Response
```json
{
"$defs": {
"FolderItem": {
"additionalProperties": false,
"description": "A single folder in ``list_folders``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
}
},
"title": "FolderItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"folders": {
"items": {
"$ref": "#/$defs/FolderItem"
},
"title": "Folders",
"type": "array"
},
"has_more": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has More"
},
"next_cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Cursor"
}
},
"required": [
"success"
],
"title": "ListFoldersOutput",
"type": "object"
}
```
## Limits & Quotas
- API key access requires a paid plan (Pro, Ultra, Teams, or Business).
- Generation cost is metered in credits; `check_status` reports
`credits.deducted` and `credits.remaining` on completion.
- `list_themes` and `list_folders` cap `limit` at 50 per page and use a
`next_cursor` cursor (pass it as `after`) for further pages.
- Every response carries rate-limit headers
(`x-ratelimit-remaining`, `x-ratelimit-remaining-daily`).
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising. Plan for
retries on the agent side based on the error string.
## Related integrations
## Links
- [Gamma](https://gamma.app)
---
# GitHub Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/github
GitHub repository and code management platform
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/github/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **GitHub** to any ModuleX agent or workflow. Repository, issue, pull request, branch, commit, and code search actions against the GitHub REST API (v3, `api.github.com`).
**Categories**: Developer Tools & Infrastructure · Version Control · Productivity · **Auth**: OAuth2, Personal Access Token · **Actions**: 16
## Authentication
### OAuth2 Authentication
Connect using GitHub OAuth (recommended for most use cases)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | GitHub OAuth App Client ID | Yes | `Iv1.xxxxxxxxxxxxxxxx` |
| Client Secret | GitHub OAuth App Client Secret | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://github.com/login/oauth/authorize`
- **Token URL**: `https://github.com/login/oauth/access_token`
- **Scopes**: `repo`, `user`, `read:org`, `workflow`
### Personal Access Token
Use your GitHub Personal Access Token (Classic or Fine-grained)
Go to GitHub Settings → Developer settings → Personal access tokens
Choose 'Tokens (classic)' OR 'Fine-grained tokens (Beta)'
Click 'Generate new token'
For Classic: Select scopes (repo, user, read:org, workflow)
For Fine-grained: Set repository access and permissions
Copy the generated token
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Personal Access Token | Your GitHub Personal Access Token (Classic: ghp_xxx or Fine-grained: github_pat_xxx) | Yes | `ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
Filter by visibility: all, public, private (Default: `all`)
Sort by: created, updated, pushed, full_name (Default: `full_name`)
Results per page (max 100) (Default: `30`)
### Response
```json
{
"$defs": {
"RepositorySummary": {
"additionalProperties": false,
"description": "One row of ``list_repositories``.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"full_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Full Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"private": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Private"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"clone_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Clone Url"
},
"ssh_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ssh Url"
},
"language": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Language"
},
"stars": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Stars"
},
"forks": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Forks"
},
"open_issues": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Open Issues"
},
"default_branch": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Default Branch"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"title": "RepositorySummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"repositories": {
"items": {
"$ref": "#/$defs/RepositorySummary"
},
"title": "Repositories",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
},
"page": {
"default": 1,
"title": "Page",
"type": "integer"
},
"per_page": {
"default": 30,
"title": "Per Page",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListRepositoriesOutput",
"type": "object"
}
```
### Parameters
Repository name
Repository description
Whether the repository is private (Default: `false`)
### Response
```json
{
"$defs": {
"RepositoryCreated": {
"additionalProperties": false,
"description": "Repository representation from ``create_repository``.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"full_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Full Name"
},
"owner": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Owner"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"clone_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Clone Url"
},
"private": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Private"
},
"default_branch": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Default Branch"
}
},
"title": "RepositoryCreated",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"repository": {
"$ref": "#/$defs/RepositoryCreated"
}
},
"required": [
"success",
"repository"
],
"title": "CreateRepositoryOutput",
"type": "object"
}
```
### Parameters
Repository owner (username or organization)
Repository name to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"message": {
"title": "Message",
"type": "string"
}
},
"required": [
"success",
"message"
],
"title": "DeleteRepositoryOutput",
"type": "object"
}
```
### Parameters
Repository owner
Repository name
### Response
```json
{
"$defs": {
"RepositoryDetailed": {
"additionalProperties": false,
"description": "Repository representation from ``get_repository``.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"full_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Full Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"private": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Private"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"clone_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Clone Url"
},
"ssh_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ssh Url"
},
"language": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Language"
},
"stars": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Stars"
},
"forks": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Forks"
},
"watchers": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Watchers"
},
"open_issues": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Open Issues"
},
"default_branch": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Default Branch"
},
"topics": {
"items": {
"type": "string"
},
"title": "Topics",
"type": "array"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"pushed_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Pushed At"
}
},
"title": "RepositoryDetailed",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"repository": {
"$ref": "#/$defs/RepositoryDetailed"
}
},
"required": [
"success",
"repository"
],
"title": "GetRepositoryOutput",
"type": "object"
}
```
### Parameters
Repository owner
Repository name
Issue state: open, closed, all (Default: `open`)
### Response
```json
{
"$defs": {
"IssueSummary": {
"additionalProperties": false,
"description": "Issue row in ``list_issues`` / single fetch in ``get_issue``.",
"properties": {
"number": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Number"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"body": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Body"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"user": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
},
"assignees": {
"items": {
"type": "string"
},
"title": "Assignees",
"type": "array"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"closed_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Closed At"
},
"comments": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Comments"
}
},
"title": "IssueSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"issues": {
"items": {
"$ref": "#/$defs/IssueSummary"
},
"title": "Issues",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
},
"page": {
"default": 1,
"title": "Page",
"type": "integer"
},
"per_page": {
"default": 30,
"title": "Per Page",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListIssuesOutput",
"type": "object"
}
```
### Parameters
Repository owner
Repository name
Issue title
Issue body
Issue labels
### Response
```json
{
"$defs": {
"IssueCreated": {
"additionalProperties": false,
"description": "Issue representation from ``create_issue``.",
"properties": {
"number": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Number"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"body": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Body"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
}
},
"title": "IssueCreated",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"issue": {
"$ref": "#/$defs/IssueCreated"
}
},
"required": [
"success",
"issue"
],
"title": "CreateIssueOutput",
"type": "object"
}
```
### Parameters
Repository owner
Repository name
Issue number
### Response
```json
{
"$defs": {
"IssueSummary": {
"additionalProperties": false,
"description": "Issue row in ``list_issues`` / single fetch in ``get_issue``.",
"properties": {
"number": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Number"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"body": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Body"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"user": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
},
"assignees": {
"items": {
"type": "string"
},
"title": "Assignees",
"type": "array"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"closed_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Closed At"
},
"comments": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Comments"
}
},
"title": "IssueSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"issue": {
"$ref": "#/$defs/IssueSummary"
}
},
"required": [
"success",
"issue"
],
"title": "GetIssueOutput",
"type": "object"
}
```
### Parameters
Repository owner
Repository name
Issue number
Issue title
Issue body
Issue state: open or closed
### Response
```json
{
"$defs": {
"IssueUpdated": {
"additionalProperties": false,
"description": "Issue representation from ``update_issue``.",
"properties": {
"number": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Number"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"body": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Body"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"title": "IssueUpdated",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"issue": {
"$ref": "#/$defs/IssueUpdated"
}
},
"required": [
"success",
"issue"
],
"title": "UpdateIssueOutput",
"type": "object"
}
```
### Parameters
Repository owner
Repository name
PR state: open, closed, all (Default: `open`)
### Response
```json
{
"$defs": {
"PullRequestSummary": {
"additionalProperties": false,
"description": "PR row in ``list_pull_requests``.",
"properties": {
"number": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Number"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"body": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Body"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"user": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User"
},
"head": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Head"
},
"base": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Base"
},
"draft": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Draft"
},
"mergeable": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Mergeable"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"merged_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Merged At"
},
"closed_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Closed At"
}
},
"title": "PullRequestSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"pull_requests": {
"items": {
"$ref": "#/$defs/PullRequestSummary"
},
"title": "Pull Requests",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
},
"page": {
"default": 1,
"title": "Page",
"type": "integer"
},
"per_page": {
"default": 30,
"title": "Per Page",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListPullRequestsOutput",
"type": "object"
}
```
### Parameters
Repository owner
Repository name
Pull request title
The name of the branch where your changes are implemented
The name of the branch you want the changes pulled into
Pull request description
### Response
```json
{
"$defs": {
"PullRequestCreated": {
"additionalProperties": false,
"description": "PR representation from ``create_pull_request``.",
"properties": {
"number": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Number"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"body": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Body"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"draft": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Draft"
},
"head": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Head"
},
"base": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Base"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
}
},
"title": "PullRequestCreated",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"pull_request": {
"$ref": "#/$defs/PullRequestCreated"
}
},
"required": [
"success",
"pull_request"
],
"title": "CreatePullRequestOutput",
"type": "object"
}
```
### Parameters
Repository owner
Repository name
Pull request number
### Response
```json
{
"$defs": {
"PullRequestDetailed": {
"additionalProperties": false,
"description": "PR representation from ``get_pull_request``.",
"properties": {
"number": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Number"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"body": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Body"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"user": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User"
},
"head": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Head"
},
"base": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Base"
},
"draft": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Draft"
},
"mergeable": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Mergeable"
},
"merged": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Merged"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"merged_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Merged At"
},
"closed_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Closed At"
},
"commits": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Commits"
},
"additions": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Additions"
},
"deletions": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Deletions"
},
"changed_files": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Changed Files"
}
},
"title": "PullRequestDetailed",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"pull_request": {
"$ref": "#/$defs/PullRequestDetailed"
}
},
"required": [
"success",
"pull_request"
],
"title": "GetPullRequestOutput",
"type": "object"
}
```
### Parameters
Repository owner
Repository name
Pull request number
Commit message for the merge
Merge method: merge, squash, rebase (Default: `merge`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"merged": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Merged"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"sha": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sha"
}
},
"required": [
"success"
],
"title": "MergePullRequestOutput",
"type": "object"
}
```
### Parameters
Repository owner
Repository name
New branch name
Source branch (defaults to default branch)
### Response
```json
{
"$defs": {
"Branch": {
"additionalProperties": false,
"description": "Branch returned by ``create_branch``.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"ref": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ref"
},
"sha": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sha"
}
},
"title": "Branch",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"branch": {
"$ref": "#/$defs/Branch"
}
},
"required": [
"success",
"branch"
],
"title": "CreateBranchOutput",
"type": "object"
}
```
### Parameters
Repository owner
Repository name
File path
Branch name (defaults to default branch)
### Response
```json
{
"$defs": {
"FileContent": {
"additionalProperties": false,
"description": "File returned by ``get_file_content`` (content is base64-decoded UTF-8).",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"path": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"content": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content"
},
"sha": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sha"
},
"download_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Download Url"
}
},
"title": "FileContent",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"file": {
"$ref": "#/$defs/FileContent"
}
},
"required": [
"success",
"file"
],
"title": "GetFileContentOutput",
"type": "object"
}
```
### Parameters
Repository owner
Repository name
Branch name
Commit message
Array of file objects with path and content
### Response
```json
{
"$defs": {
"CommitCreated": {
"additionalProperties": false,
"description": "Commit returned by ``create_commit``.",
"properties": {
"sha": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sha"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"branch": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Branch"
}
},
"title": "CommitCreated",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"commit": {
"$ref": "#/$defs/CommitCreated"
}
},
"required": [
"success",
"commit"
],
"title": "CreateCommitOutput",
"type": "object"
}
```
### Parameters
Search query
Sort by: indexed (default) (Default: `indexed`)
Results per page (max 100) (Default: `30`)
### Response
```json
{
"$defs": {
"SearchCodeItem": {
"additionalProperties": false,
"description": "One result row of ``search_code``.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"path": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path"
},
"repository": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Repository"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"sha": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sha"
}
},
"title": "SearchCodeItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"total_count": {
"default": 0,
"title": "Total Count",
"type": "integer"
},
"items": {
"items": {
"$ref": "#/$defs/SearchCodeItem"
},
"title": "Items",
"type": "array"
},
"page": {
"default": 1,
"title": "Page",
"type": "integer"
},
"per_page": {
"default": 30,
"title": "Per Page",
"type": "integer"
}
},
"required": [
"success"
],
"title": "SearchCodeOutput",
"type": "object"
}
```
## Limits & Quotas
- **Authenticated REST API:** 5,000 requests per hour per token.
- **Search API** (`search_code`): 30 requests per minute, separate
quota — and `q` must be at least one valid qualifier (e.g.
`repo:owner/name` or `language:python`).
- **`create_commit`** makes five sequential API calls (ref, base commit,
one blob per file, tree, commit, ref update). Budget accordingly when
committing many files.
- **`delete_repository`** is irreversible and requires the token to
carry the `delete_repo` scope; Fine-grained tokens additionally need
the *Administration: write* permission.
## Related integrations
## Links
- [GitHub](https://github.com)
---
# GitLab Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/gitlab
GitLab repository and project management platform
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/gitlab/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **GitLab** to any ModuleX agent or workflow. Repository and project management platform for the GitLab REST API (`gitlab.com/api/v4`).
**Categories**: Developer Tools & Infrastructure · Version Control · Project Management · **Auth**: OAuth2 · **Actions**: 12
## Authentication
### OAuth2 Authentication
Connect using GitLab OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | GitLab OAuth App Client ID | Yes | `-` |
| Client Secret | GitLab OAuth App Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://gitlab.com/oauth/authorize`
- **Token URL**: `https://gitlab.com/oauth/token`
- **Scopes**: `api`
## Available Actions
### Parameters
The project ID, as displayed in the main project page
The branch name or commit SHA to create the new branch from
The name of the branch to create
### Response
```json
{
"$defs": {
"BranchCommit": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"short_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Short Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"author_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Author Name"
},
"author_email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Author Email"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"title": "BranchCommit",
"type": "object"
},
"BranchSummary": {
"additionalProperties": false,
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"commit": {
"anyOf": [
{
"$ref": "#/$defs/BranchCommit"
},
{
"type": "null"
}
],
"default": null
},
"merged": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Merged"
},
"protected": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Protected"
},
"developers_can_push": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Developers Can Push"
},
"developers_can_merge": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Developers Can Merge"
},
"can_push": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Push"
},
"web_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web Url"
}
},
"title": "BranchSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"branch": {
"anyOf": [
{
"$ref": "#/$defs/BranchSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateBranchOutput",
"type": "object"
}
```
### Parameters
The ID of the group
The title of the epic
The description of the epic
List of label names for the epic
The internal ID of the parent epic (requires GitLab Premium or Ultimate)
The color of the epic (introduced in GitLab 14.8)
Whether the epic should be confidential
When the epic was created, ISO 8601 format (requires admin or owner privileges)
Whether start date should be sourced from start_date_fixed or from milestones
Whether due date should be sourced from due_date_fixed or from milestones
The fixed start date of the epic, ISO 8601 format (relevant when start_date_is_fixed is true)
The fixed due date of the epic, ISO 8601 format (relevant when due_date_is_fixed is true)
### Response
```json
{
"$defs": {
"EpicSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"iid": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Iid"
},
"group_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Group Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"confidential": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Confidential"
},
"web_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web Url"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
}
},
"title": "EpicSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"epic": {
"anyOf": [
{
"$ref": "#/$defs/EpicSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateEpicOutput",
"type": "object"
}
```
### Parameters
The project ID, as displayed in the main project page
The title of the issue
The description of the issue
List of label names for the issue
List of user IDs to assign the issue to
### Response
```json
{
"$defs": {
"IssueSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"iid": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Iid"
},
"project_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Project Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"web_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web Url"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"closed_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Closed At"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
},
"assignees": {
"items": {
"type": "string"
},
"title": "Assignees",
"type": "array"
}
},
"title": "IssueSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"issue": {
"anyOf": [
{
"$ref": "#/$defs/IssueSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateIssueOutput",
"type": "object"
}
```
### Parameters
The project ID, as displayed in the main project page
The internal ID of the project issue
### Response
```json
{
"$defs": {
"IssueSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"iid": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Iid"
},
"project_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Project Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"web_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web Url"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"closed_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Closed At"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
},
"assignees": {
"items": {
"type": "string"
},
"title": "Assignees",
"type": "array"
}
},
"title": "IssueSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"issue": {
"anyOf": [
{
"$ref": "#/$defs/IssueSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetIssueOutput",
"type": "object"
}
```
### Parameters
The project ID, as displayed in the main project page
The name of the branch
### Response
```json
{
"$defs": {
"BranchCommit": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"short_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Short Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"author_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Author Name"
},
"author_email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Author Email"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"title": "BranchCommit",
"type": "object"
},
"BranchSummary": {
"additionalProperties": false,
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"commit": {
"anyOf": [
{
"$ref": "#/$defs/BranchCommit"
},
{
"type": "null"
}
],
"default": null
},
"merged": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Merged"
},
"protected": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Protected"
},
"developers_can_push": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Developers Can Push"
},
"developers_can_merge": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Developers Can Merge"
},
"can_push": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Push"
},
"web_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web Url"
}
},
"title": "BranchSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"branch": {
"anyOf": [
{
"$ref": "#/$defs/BranchSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetRepoBranchOutput",
"type": "object"
}
```
### Parameters
The project ID, as displayed in the main project page
The name of a repository branch, tag, or revision range; defaults to the default branch if not given
Maximum number of commits to return (per_page) (Default: `100`)
### Response
```json
{
"$defs": {
"CommitSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"short_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Short Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"author_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Author Name"
},
"author_email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Author Email"
},
"authored_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Authored Date"
},
"committed_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Committed Date"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"web_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web Url"
}
},
"title": "CommitSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"commits": {
"items": {
"$ref": "#/$defs/CommitSummary"
},
"title": "Commits",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListCommitsOutput",
"type": "object"
}
```
### Parameters
Limit to groups where the user has at least this access level: 10 (Guest), 20 (Reporter), 30 (Developer), 40 (Maintainer), 50 (Owner)
Limit to top-level groups, excluding all subgroups
Return groups matching this search string
Order groups by: name, path, id, or similarity (must be similarity when search is provided)
Sort order: asc or desc (Default: `asc`)
Limit to groups that are not archived and not marked for deletion
Limit to groups that are archived
### Response
```json
{
"$defs": {
"GroupSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"path": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"visibility": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Visibility"
},
"web_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web Url"
},
"full_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Full Name"
},
"full_path": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Full Path"
}
},
"title": "GroupSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"groups": {
"items": {
"$ref": "#/$defs/GroupSummary"
},
"title": "Groups",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListGroupsOutput",
"type": "object"
}
```
### Parameters
The project ID, as displayed in the main project page
Filter results by name, email, or username (partial values accepted)
List of user IDs to filter results to
List of user IDs to exclude from results
Return seat information for each member if available
### Response
```json
{
"$defs": {
"MemberSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"username": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Username"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"access_level": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Access Level"
},
"web_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web Url"
}
},
"title": "MemberSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"members": {
"items": {
"$ref": "#/$defs/MemberSummary"
},
"title": "Members",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListProjectMembersOutput",
"type": "object"
}
```
### Parameters
The project ID, as displayed in the main project page
Return branches containing this search string (use ^term and term$ for prefix/suffix matching)
### Response
```json
{
"$defs": {
"BranchCommit": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"short_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Short Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"author_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Author Name"
},
"author_email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Author Email"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"title": "BranchCommit",
"type": "object"
},
"BranchSummary": {
"additionalProperties": false,
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"commit": {
"anyOf": [
{
"$ref": "#/$defs/BranchCommit"
},
{
"type": "null"
}
],
"default": null
},
"merged": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Merged"
},
"protected": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Protected"
},
"developers_can_push": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Developers Can Push"
},
"developers_can_merge": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Developers Can Merge"
},
"can_push": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Push"
},
"web_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web Url"
}
},
"title": "BranchSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"branches": {
"items": {
"$ref": "#/$defs/BranchSummary"
},
"title": "Branches",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListRepoBranchesOutput",
"type": "object"
}
```
### Parameters
The project ID, as displayed in the main project page
Search issues against their title and description
List of label names; issues must have all labels to be returned
Return issues by state: all, opened, or closed (Default: `all`)
Return issues assigned to the given user ID
Maximum number of issues to return (per_page) (Default: `100`)
### Response
```json
{
"$defs": {
"IssueSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"iid": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Iid"
},
"project_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Project Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"web_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web Url"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"closed_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Closed At"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
},
"assignees": {
"items": {
"type": "string"
},
"title": "Assignees",
"type": "array"
}
},
"title": "IssueSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"issues": {
"items": {
"$ref": "#/$defs/IssueSummary"
},
"title": "Issues",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchIssuesOutput",
"type": "object"
}
```
### Parameters
The ID of the group
The internal ID of the epic
The title of the epic
The description of the epic
List of label names for the epic (set empty to unassign all)
Labels to add to the epic
Labels to remove from the epic
The ID of a parent epic (available in GitLab 14.6+)
State event for the epic: close or reopen
Whether the epic should be confidential
The color of the epic
When the epic was updated, ISO 8601 format (requires admin or owner privileges)
Whether start date should be sourced from start_date_fixed or from milestones
Whether due date should be sourced from due_date_fixed or from milestones
The fixed start date of the epic, ISO 8601 format (relevant when start_date_is_fixed is true)
The fixed due date of the epic, ISO 8601 format (relevant when due_date_is_fixed is true)
### Response
```json
{
"$defs": {
"EpicSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"iid": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Iid"
},
"group_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Group Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"confidential": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Confidential"
},
"web_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web Url"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
}
},
"title": "EpicSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"epic": {
"anyOf": [
{
"$ref": "#/$defs/EpicSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UpdateEpicOutput",
"type": "object"
}
```
### Parameters
The project ID, as displayed in the main project page
The internal ID of the issue
The title of the issue
The description of the issue
List of label names for the issue (set empty to unassign all)
List of user IDs to assign the issue to (set to 0 or empty to unassign all)
State event for the issue: close or reopen
Whether the issue discussion is locked (only project members can add or edit comments when locked)
### Response
```json
{
"$defs": {
"IssueSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"iid": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Iid"
},
"project_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Project Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"web_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web Url"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"closed_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Closed At"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
},
"assignees": {
"items": {
"type": "string"
},
"title": "Assignees",
"type": "array"
}
},
"title": "IssueSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"issue": {
"anyOf": [
{
"$ref": "#/$defs/IssueSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UpdateIssueOutput",
"type": "object"
}
```
## Limits & Quotas
- **Authenticated requests**: 2,000 requests per minute per user (GitLab.com).
- **Unauthenticated**: 500 requests per minute.
- **Epics API**: restricted to GitLab Premium and Ultimate tiers.
- **Error model**: non-2xx responses raise `httpx.HTTPStatusError` (Pattern A). The agent or runtime catches the exception at a higher layer.
## Related integrations
## Links
- [GitLab](https://gitlab.com)
---
# Gmail Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/gmail
Google Gmail email service for sending, reading, and managing emails.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/gmail/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Gmail** to any ModuleX agent or workflow. Gmail integration via the Gmail REST v1 API (`www.googleapis.com/gmail/v1`). Send email + list labels. Pure HTTP — does **not** depend on the `google-api-python-client` SDK.
**Categories**: Communication · Communication & Collaboration · Email · Productivity · **Auth**: OAuth2, Service Account / Access Token · **Actions**: 2
## Authentication
### OAuth2 Authentication
Connect using Google OAuth2 (recommended). Provides secure access to Gmail.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Google OAuth2 Client ID from Google Cloud Console | Yes | `123456789-xxxxxxxxxxxxxxxx.apps.googleusercontent.com` |
| Client Secret | Google OAuth2 Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Scopes**: `https://www.googleapis.com/auth/gmail.send`, `https://www.googleapis.com/auth/gmail.labels`
### Service Account / Access Token
Use a pre-generated access token or service account credentials
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Access Token | A valid Google OAuth2 access token with Gmail scopes | Yes | `-` |
## Available Actions
### Parameters
Recipient email address
Email subject line
Email body content
CC recipients (comma-separated)
BCC recipients (comma-separated)
Whether the body is HTML content (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"thread_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Thread Id"
},
"label_ids": {
"items": {
"type": "string"
},
"title": "Label Ids",
"type": "array"
}
},
"required": [
"success"
],
"title": "SendMessageOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"labels": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Labels",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListLabelsOutput",
"type": "object"
}
```
## Limits & Quotas
- `send_message` builds a base64url-encoded MIME message locally
(no SDK dep).
- Sending is limited to 500 messages/day (consumer accounts) or
2000/day (Google Workspace).
- 60s timeout for send, 30s for label listing.
## Related integrations
## Links
- [Gmail](https://mail.google.com)
---
# GoDaddy Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/godaddy
Domain registration, availability checking, and management via the GoDaddy API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/godaddy/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **GoDaddy** to any ModuleX agent or workflow. Domain registration, availability checking, and management via the GoDaddy REST API (`api.godaddy.com/v1`).
**Categories**: Cloud Infrastructure · Domains · Infrastructure · Web Hosting · **Auth**: GoDaddy API Key + Secret · **Actions**: 5
## Authentication
### GoDaddy API Key + Secret
Authenticate using a GoDaddy API key and secret pair. The Authorization header is built as 'sso-key <key>:<secret>'.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| API Key | Your GoDaddy API Key from developer.godaddy.com | Yes | `xxxxxxxxxxxxxxxx` |
| API Secret | Your GoDaddy API Secret from developer.godaddy.com | Yes | `xxxxxxxxxxxxxxxxxxxxxxxx` |
| API URL | GoDaddy API base URL. Use https://api.godaddy.com for production or https://api.ote-godaddy.com for the test environment | Yes | `https://api.godaddy.com` |
## Available Actions
### Parameters
The domain name to check availability for (e.g. example.com)
Optimize for time (FAST) or accuracy (FULL). Allowed values: FAST, FULL
Whether to include domains available for transfer. If true, check_type is ignored
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"available": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Available"
},
"domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Domain"
},
"definitive": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Definitive"
},
"price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Price"
},
"currency": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Currency"
},
"period": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Period"
}
},
"required": [
"success"
],
"title": "CheckDomainAvailabilityOutput",
"type": "object"
}
```
### Parameters
Filter by status. Array of strings: ACTIVE, CANCELLED, etc.
Filter by status group. Array of strings: VISIBLE, INACTIVE, RENEWABLE, etc.
Maximum number of domains to return
Marker domain to use as the offset in results
Optional details to include: authCode, contacts, nameServers
Only include results modified since this date (ISO 8601 format)
### Response
```json
{
"$defs": {
"DomainSummary": {
"additionalProperties": false,
"description": "A domain summary object from the list domains endpoint.",
"properties": {
"domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Domain"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"expires": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Expires"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"renewable": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Renewable"
}
},
"title": "DomainSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"domains": {
"items": {
"$ref": "#/$defs/DomainSummary"
},
"title": "Domains",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListDomainsOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"TldInfo": {
"additionalProperties": false,
"description": "A TLD entry from the list TLDs endpoint.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
}
},
"title": "TldInfo",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"tlds": {
"items": {
"$ref": "#/$defs/TldInfo"
},
"title": "Tlds",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListTldsOptionsOutput",
"type": "object"
}
```
### Parameters
The domain name to renew (e.g. example.com)
Number of years to extend the domain (1-10). Defaults to original purchase period when omitted
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"order_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Order Id"
},
"item_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Item Count"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"currency": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Currency"
}
},
"required": [
"success"
],
"title": "RenewDomainOutput",
"type": "object"
}
```
### Parameters
Domain name or keywords for which alternative domain names will be suggested
Two-letter ISO country code as a hint for target region
City name as a hint for target region
Sources to query: CC_TLD, EXTENSION, KEYWORD_SPIN, PREMIUM
Top-level domains to include in suggestions (e.g. com, net, org)
Maximum length of second-level domain
Minimum length of second-level domain
Maximum number of suggestions to return
Maximum time in milliseconds to wait for responses
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"suggestions": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Suggestions",
"type": "array"
}
},
"required": [
"success"
],
"title": "SuggestDomainsOutput",
"type": "object"
}
```
## Limits & Quotas
- **Production API**: 60 requests per minute per API key (per GoDaddy developer documentation).
- **OTE (test) API**: Lower rate limits; intended for development only.
- **Renewal actions** incur actual charges on the account.
- **Error model**: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [GoDaddy](https://www.godaddy.com)
---
# Gong Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/gong
Revenue intelligence platform for recording, transcribing, and analyzing sales conversations
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/gong/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Gong** to any ModuleX agent or workflow. Revenue intelligence platform for recording, transcribing, and analyzing sales conversations via the Gong REST API (your per-tenant `https://-.api.gong.io/v2` base URL).
**Categories**: Sales · Revenue Intelligence · Conversation Analytics · **Auth**: Gong API Key · **Actions**: 5
## Authentication
### Gong API Key
Authenticate with a Gong Access Key + Access Key Secret (Company Settings -> API), sent as HTTP Basic auth.
Sign in to Gong as a technical administrator
Go to Company Settings -> Ecosystem -> API (https://app.gong.io/company/api)
Click 'Create' to generate an Access Key and Access Key Secret (the Secret is shown only once)
Find your API base URL at https://app.gong.io/company/api-authentication (e.g. https://us-12345.api.gong.io)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Access Key | Gong API Access Key | Yes | `-` |
| Access Key Secret | Gong API Access Key Secret (shown only once at creation) | Yes | `-` |
| API Base URL | Your Gong API base URL (region/tenant-specific), e.g. https://us-12345.api.gong.io | Yes | `https://us-12345.api.gong.io` |
## Available Actions
### Parameters
A call's unique identifier in the PBX or recording system. Used to prevent duplicate uploads.
The actual date and time when the call started in ISO-8601 format (e.g., 2018-02-18T02:30:00-07:00 or 2018-02-18T08:00:00Z).
Whether the call is Inbound, Outbound, Conference, or Unknown.
The Gong internal user ID of the team member who hosted the call.
A list of the call's participants as JSON objects. Each party can have: phoneNumber, emailAddress, name, mediaChannelId.
The title of the call, available for indexing and search.
The purpose of the call. Free text up to 255 characters.
The date and time the call was scheduled to begin in ISO-8601 format.
The date and time the call was scheduled to end in ISO-8601 format.
The actual call duration in seconds.
The disposition of the call. Free text up to 255 characters.
The URL of the conference call by which users join the meeting.
Code identifying the conferencing/telephony system: zoom, clearslide, gotomeeting, ringcentral, outreach, insidesales.
The URL from which Gong can download the media file. Must be unique, max 1.5GB.
Optional workspace identifier for call placement.
Language code for transcription (e.g., en-US, fr-FR). Optional; Gong auto-detects if not set.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Request Id"
},
"call_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Call Id"
}
},
"required": [
"success"
],
"title": "AddNewCallOutput",
"type": "object"
}
```
### Parameters
Date and time (ISO-8601) from which to list recorded calls.
Date and time (ISO-8601) until which to list recorded calls.
The ID of the workspace to filter by.
List of call ID strings to filter. If not supplied, returns all calls in date range.
List of user ID strings. If supplied, returns only calls hosted by these users.
Maximum number of results to return. (Default: `600`)
Context level: None, Basic (add links), or Extended (include link data). (Default: `None`)
Timing for context data: 'Now' or 'TimeOfCall' or both. Only valid when context is Extended.
Whether to include parties in the response. (Default: `false`)
Fields to include for content: structure, topics, trackers, trackerOccurrences, pointsOfInterest, brief, outline, highlights, callOutcome, keyPoints (boolean values).
Fields to include for interaction: speakers, video, personInteractionStats, questions (boolean values).
Whether to include public comments in the response. (Default: `false`)
Whether to include media in the response. (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"calls": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Calls",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetExtensiveDataOutput",
"type": "object"
}
```
### Parameters
Date and time (ISO-8601) from which to list recorded calls.
Date and time (ISO-8601) until which to list recorded calls.
Pagination cursor returned by a previous call.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Request Id"
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cursor"
},
"calls": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Calls",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListCallsOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"Workspace": {
"additionalProperties": false,
"description": "A Gong workspace entry.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
}
},
"title": "Workspace",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"workspaces": {
"items": {
"$ref": "#/$defs/Workspace"
},
"title": "Workspaces",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListWorkspaceIdOptionsOutput",
"type": "object"
}
```
### Parameters
Date and time (ISO-8601) from which to filter calls.
Date and time (ISO-8601) until which to filter calls.
The ID of the workspace to filter by.
List of call ID strings to retrieve transcripts for.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"call_transcripts": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Call Transcripts",
"type": "array"
}
},
"required": [
"success"
],
"title": "RetrieveTranscriptsOfCallsOutput",
"type": "object"
}
```
## Limits & Quotas
- Gong API rate limits vary by endpoint and plan tier. Consult your Gong admin for specific limits.
- The `get_extensive_data` action paginates internally up to `max_results` (default 600).
- Error model: non-2xx responses are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Gong](https://www.gong.io)
---
# Google Ad Manager Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-ad-manager
Programmatic advertising platform for managing ad inventory, reporting, and campaign delivery
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_ad_manager/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google Ad Manager** to any ModuleX agent or workflow. Programmatic advertising platform for managing ad inventory, reporting, and campaign delivery via the Google Ad Manager REST API (`admanager.googleapis.com/v1`).
**Categories**: Marketing & Advertising · Advertising · Marketing · **Auth**: OAuth2 · **Actions**: 2
## Authentication
### OAuth2 Authentication
Connect using Google OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Google OAuth App Client ID | Yes | `-` |
| Client Secret | Google OAuth App Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Scopes**: `https://www.googleapis.com/auth/admanager`
## Available Actions
### Parameters
The parent resource where this Report will be created. Format: networks/{networkCode}
Identifier. The resource name of the report. Format: networks/{networkCode}/reports/{reportId}
The visibility of the report. Allowed values: HIDDEN, DRAFT, SAVED
The list of dimension identifiers to report on
The list of metric identifiers to report on
The type of this report. Allowed values: REPORT_TYPE_UNSPECIFIED, HISTORICAL
The date range type of this report. Allowed values: fixed, relative
The display name of the report
The options for a scheduled report (ScheduleOptions schema)
The filters for this report. Each element is a JSON object conforming to the Filter schema
The time zone for the date range (IANA format). Defaults to publisher time zone
ISO 4217 currency code. Defaults to publisher currency code
Custom Dimension keys for CUSTOM_DIMENSION_* dimensions
Custom field IDs for LINE_ITEM_CUSTOM_FIELD_* dimensions
Custom field IDs for ORDER_CUSTOM_FIELD_* dimensions
Custom field IDs for CREATIVE_CUSTOM_FIELD_* dimensions
Time period column for comparison. Allowed values: TIME_PERIOD_COLUMN_UNSPECIFIED, TIME_PERIOD_COLUMN_DATE, TIME_PERIOD_COLUMN_WEEK, TIME_PERIOD_COLUMN_MONTH, TIME_PERIOD_COLUMN_QUARTER
List of flags for this report (Flag schema objects)
Default sorts for this report (Sort schema objects)
Year of the start date (1-9999). Required when date_range is 'fixed'
Month of the start date (1-12). Required when date_range is 'fixed'
Day of the start date (1-31). Required when date_range is 'fixed'
Year of the end date (1-9999). Required when date_range is 'fixed'
Month of the end date (1-12). Required when date_range is 'fixed'
Day of the end date (1-31). Required when date_range is 'fixed'
Relative date range identifier (e.g. TODAY, YESTERDAY, LAST_7_DAYS). Required when date_range is 'relative'
Comparison date range type. Allowed values: fixed, relative
Year of comparison start date. Required when comparison_date_range is 'fixed'
Month of comparison start date. Required when comparison_date_range is 'fixed'
Day of comparison start date. Required when comparison_date_range is 'fixed'
Year of comparison end date. Required when comparison_date_range is 'fixed'
Month of comparison end date. Required when comparison_date_range is 'fixed'
Day of comparison end date. Required when comparison_date_range is 'fixed'
Relative comparison date range identifier (e.g. PREVIOUS_PERIOD, SAME_PERIOD_PREVIOUS_YEAR). Required when comparison_date_range is 'relative'
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateReportOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"networks": {
"items": {
"type": "string"
},
"title": "Networks",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListNetworkOptionsOutput",
"type": "object"
}
```
## Limits & Quotas
- Google Ad Manager API enforces per-network rate limits; consult your network's quota settings in the Ad Manager UI.
- Standard quota: 10,000 requests per day per project (default; can be increased via Google Cloud console).
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Google Ad Manager](https://admanager.google.com)
---
# Google Ads Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-ads
Google Ads API integration: run GAQL reports across Campaigns, Ad Groups, Ads, and Customers; create customer lists; send offline conversions; generate keyword ideas.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_ads/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google Ads** to any ModuleX agent or workflow. Google Ads API integration covering GAQL reports across Campaigns, Ad Groups, Ads, and Customers; Customer Match list management; offline conversion uploads; and keyword idea generation against the REST API at `googleads.googleapis.com`.
**Categories**: Marketing & Advertising · Analytics · Business Services · **Auth**: OAuth2 · **Actions**: 10
## Authentication
### OAuth2 Authentication
Connect using Google OAuth2 (recommended). Requires a Google Ads API developer token in addition to the OAuth credentials.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Google OAuth2 Client ID from Cloud Console. | Yes | `123456789-xxxxxxxxxxxxxxxx.apps.googleusercontent.com` |
| Client Secret | Google OAuth2 Client Secret. | Yes | `GOCSPX-xxxxxxxxxxxxxxxxxxxx` |
| Developer Token | Google Ads API developer-token header value. Apply at https://ads.google.com/aw/apicenter (Manager Account required). | Yes | `xxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Scopes**: `https://www.googleapis.com/auth/adwords`
## Available Actions
### Parameters
Login customer ID (the Manager Account ID used as login-customer-id header). Digits only, no dashes.
ID of the CRM-based customer list to update.
Email address of the contact to add.
Managed customer (client) ID. Defaults to account_id when omitted.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"offline_user_data_job_resource_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Offline User Data Job Resource Name"
},
"operation_resource_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Operation Resource Name"
}
},
"required": [
"success"
],
"title": "AddContactToListByEmailOutput",
"type": "object"
}
```
### Parameters
Login customer ID (login-customer-id header).
List of ad_group fields to select (e.g. 'ad_group.id', 'ad_group.name'). Each element is a string; the 'ad_group.' prefix is auto-added if missing.
List of segments (e.g. 'segments.date'). Each element is a string; the 'segments.' prefix is auto-added.
List of metric fields (e.g. 'metrics.clicks'). Each element is a string; the 'metrics.' prefix is auto-added.
Optional list of ad_group IDs to filter by. Each element is a string (the numeric ID).
Date range constant: CUSTOM, TODAY, YESTERDAY, LAST_7_DAYS, LAST_14_DAYS, LAST_30_DAYS, THIS_MONTH, LAST_MONTH, THIS_WEEK_SUN_TODAY, THIS_WEEK_MON_TODAY, LAST_WEEK_SUN_SAT, LAST_WEEK_MON_SUN, LAST_BUSINESS_WEEK.
Custom range start (YYYY-MM-DD); required when date_range=CUSTOM.
Custom range end (YYYY-MM-DD); required when date_range=CUSTOM.
Field name to order results by.
Order direction: ASC or DESC. (Default: `ASC`)
Maximum number of results to return.
Managed customer ID; defaults to account_id when omitted.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Query"
},
"results": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Results",
"type": "array"
},
"field_mask": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Field Mask"
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Request Id"
}
},
"required": [
"success"
],
"title": "CreateAdGroupReportOutput",
"type": "object"
}
```
### Parameters
Login customer ID (login-customer-id header).
List of ad_group_ad fields to select (strings).
List of segments (strings).
List of metric fields (strings).
Optional list of ad IDs to filter by (strings).
Date range constant. See create_ad_group_report for valid values.
Custom range start (YYYY-MM-DD); required when date_range=CUSTOM.
Custom range end (YYYY-MM-DD); required when date_range=CUSTOM.
Field name to order results by.
Order direction: ASC or DESC. (Default: `ASC`)
Maximum number of results to return.
Managed customer ID; defaults to account_id when omitted.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Query"
},
"results": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Results",
"type": "array"
},
"field_mask": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Field Mask"
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Request Id"
}
},
"required": [
"success"
],
"title": "CreateAdReportOutput",
"type": "object"
}
```
### Parameters
Login customer ID (login-customer-id header).
List of campaign fields to select (strings).
List of segments (strings).
List of metric fields (strings).
Optional list of campaign IDs to filter by (strings).
Date range constant. See create_ad_group_report for valid values.
Custom range start (YYYY-MM-DD); required when date_range=CUSTOM.
Custom range end (YYYY-MM-DD); required when date_range=CUSTOM.
Field name to order results by.
Order direction: ASC or DESC. (Default: `ASC`)
Maximum number of results to return.
Managed customer ID; defaults to account_id when omitted.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Query"
},
"results": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Results",
"type": "array"
},
"field_mask": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Field Mask"
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Request Id"
}
},
"required": [
"success"
],
"title": "CreateCampaignReportOutput",
"type": "object"
}
```
### Parameters
Login customer ID (login-customer-id header).
Name of the user list.
Which UserList variant to create. One of: crmBasedUserList, ruleBasedUserList, logicalUserList, basicUserList, lookalikeUserList. Determines which fields list_type_data should populate.
Variant-specific payload. Merged under the list_type key. See https://developers.google.com/google-ads/api/reference/rpc/v21/UserList for the per-variant schema. (Default: `{}`)
Optional description of the user list.
Additional top-level UserList fields to merge into the create payload (e.g. membershipLifeSpan). (Default: `{}`)
Managed customer ID; defaults to account_id when omitted.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"resource_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Resource Name"
}
},
"required": [
"success"
],
"title": "CreateCustomerListOutput",
"type": "object"
}
```
### Parameters
Login customer ID (login-customer-id header).
List of customer fields to select (strings).
List of segments (strings).
List of metric fields (strings).
Optional list of customer IDs to filter by (strings).
Date range constant. See create_ad_group_report for valid values.
Custom range start (YYYY-MM-DD); required when date_range=CUSTOM.
Custom range end (YYYY-MM-DD); required when date_range=CUSTOM.
Field name to order results by.
Order direction: ASC or DESC. (Default: `ASC`)
Maximum number of results to return.
Managed customer ID; defaults to account_id when omitted.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Query"
},
"results": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Results",
"type": "array"
},
"field_mask": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Field Mask"
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Request Id"
}
},
"required": [
"success"
],
"title": "CreateCustomerReportOutput",
"type": "object"
}
```
### Parameters
Login customer ID (login-customer-id header).
Resource name to FROM-clause against (e.g. campaign, ad_group, ad_group_ad, customer).
List of resource fields to select (strings). The resource prefix is auto-added if missing.
List of segments (strings).
List of metric fields (strings).
Optional list of resource IDs to filter by (strings).
Date range constant. See create_ad_group_report for valid values.
Custom range start (YYYY-MM-DD); required when date_range=CUSTOM.
Custom range end (YYYY-MM-DD); required when date_range=CUSTOM.
Field name to order results by.
Order direction: ASC or DESC. (Default: `ASC`)
Maximum number of results to return.
Managed customer ID; defaults to account_id when omitted.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Query"
},
"results": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Results",
"type": "array"
},
"field_mask": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Field Mask"
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Request Id"
}
},
"required": [
"success"
],
"title": "CreateReportOutput",
"type": "object"
}
```
### Parameters
Login customer ID (login-customer-id header).
Managed customer ID to run the request against (required by the keyword ideas service).
Body of the GenerateKeywordIdeasRequest. See https://developers.google.com/google-ads/api/reference/rpc/v22/KeywordPlanIdeaService/GenerateKeywordIdeas for the required structure (e.g. language, geoTargetConstants, keywordSeed). (Default: `{}`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"results": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Results",
"type": "array"
},
"total_size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Size"
},
"next_page_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page Token"
}
},
"required": [
"success"
],
"title": "GenerateKeywordIdeasOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"AccessibleCustomer": {
"additionalProperties": false,
"description": "One entry returned from ``customers:listAccessibleCustomers``.",
"properties": {
"resource_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Resource Name"
},
"customer_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Customer Id"
}
},
"title": "AccessibleCustomer",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"customers": {
"items": {
"$ref": "#/$defs/AccessibleCustomer"
},
"title": "Customers",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListAccountIdOptionsOutput",
"type": "object"
}
```
### Parameters
Login customer ID (login-customer-id header).
Name of the conversion action.
ConversionActionType enum value (e.g. UPLOAD_CLICKS, UPLOAD_CALLS, WEBPAGE). See https://developers.google.com/google-ads/api/reference/rpc/v21/ConversionActionTypeEnum.ConversionActionType.
Additional ConversionAction fields to merge into the create payload (e.g. category, status, valueSettings). (Default: `{}`)
Managed customer ID; defaults to account_id when omitted.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"resource_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Resource Name"
}
},
"required": [
"success"
],
"title": "SendOfflineConversionOutput",
"type": "object"
}
```
## Limits & Quotas
- **Daily operations quota** depends on the developer-token access level (Test, Basic, Standard). Standard tokens allow 15,000 operations/day initially. See https://developers.google.com/google-ads/api/docs/access-levels.
- **Customer Match lists** typically take 6 to 12 hours to update after `add_contact_to_list_by_email` runs.
- **`generate_keyword_ideas`** counts against the same quota and may be rate-limited per minute on Basic-access tokens.
- **Error model**: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising. The error string includes the API status code and body excerpt.
## Related integrations
## Links
- [Google Ads](https://ads.google.com)
---
# Google Analytics Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-analytics
Manage Google Analytics 4 properties, list accounts, configure key events, and run analytics reports against the Google Analytics Admin and Data APIs.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_analytics/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google Analytics** to any ModuleX agent or workflow. Manage Google Analytics 4 properties, list accounts, configure key events, and run analytics reports against the Google Analytics Admin (`analyticsadmin.googleapis.com`) and Data (`analyticsdata.googleapis.com`) APIs.
**Categories**: Analytics & Data · Analytics & Reporting · Marketing · Productivity & Collaboration · **Auth**: OAuth2 · **Actions**: 6
## Authentication
### OAuth2 Authentication
Connect using Google OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Google Cloud OAuth 2.0 Client ID | Yes | `1234567890-abcdefghijklmnop.apps.googleusercontent.com` |
| Client Secret | Google Cloud OAuth 2.0 Client Secret | Yes | `GOCSPX-xxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Scopes**: `https://www.googleapis.com/auth/analytics.edit`, `https://www.googleapis.com/auth/analytics.readonly`
## Available Actions
### Parameters
Maximum number of accounts to return per page. The service may return fewer than this value. If unspecified, at most 50 accounts are returned (max 200). (Default: `50`)
Optional page token from a previous response, used to retrieve the next page of accounts.
### Response
```json
{
"$defs": {
"AccountSummary": {
"additionalProperties": false,
"description": "A Google Analytics account (admin API).",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"account": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Account"
}
},
"title": "AccountSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"accounts": {
"items": {
"$ref": "#/$defs/AccountSummary"
},
"title": "Accounts",
"type": "array"
},
"next_page_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page Token"
}
},
"required": [
"success"
],
"title": "ListAccountOptionsOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"PropertySummary": {
"additionalProperties": false,
"description": "A Google Analytics property summary (admin API).",
"properties": {
"property": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Property"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"property_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Property Type"
},
"parent": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Parent"
}
},
"title": "PropertySummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"properties": {
"type": "array",
"items": {
"$ref": "#/$defs/PropertySummary"
},
"title": "Properties"
}
},
"required": [
"success"
],
"title": "ListPropertyOptionsOutput",
"type": "object"
}
```
### Parameters
The parent account resource name, e.g. 'accounts/123456789'. Use list_account_options to discover available accounts.
Human-readable display name for the new property. Max 100 UTF-16 code units.
Reporting time zone for the property. Must be a valid IANA timezone identifier, e.g. 'America/Los_Angeles', 'Europe/London', 'Asia/Tokyo'.
Industry category associated with the property. Valid values include AUTOMOTIVE, FINANCE, HEALTHCARE, TECHNOLOGY, TRAVEL, ARTS_AND_ENTERTAINMENT, GAMES, SHOPPING, JOBS_AND_EDUCATION, and others; pass INDUSTRY_CATEGORY_UNSPECIFIED if unsure.
ISO 4217 currency code used in reports involving monetary values, e.g. 'USD', 'EUR', 'JPY'.
### Response
```json
{
"$defs": {
"PropertyResource": {
"additionalProperties": false,
"description": "A full GA4 property resource (admin API).",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"parent": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Parent"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"industry_category": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Industry Category"
},
"time_zone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Time Zone"
},
"currency_code": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Currency Code"
},
"property_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Property Type"
},
"create_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Create Time"
},
"update_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Update Time"
}
},
"title": "PropertyResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"property": {
"anyOf": [
{
"$ref": "#/$defs/PropertyResource"
},
{
"type": "null"
}
],
"default": null
},
"raw": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Raw"
}
},
"required": [
"success"
],
"title": "CreateGa4PropertyOutput",
"type": "object"
}
```
### Parameters
Parent property resource name where the key event will be created. Format: 'properties/123'.
Immutable event name for this key event. Examples: 'click', 'purchase', 'sign_up'.
Method by which the key event is counted across multiple events within a session. Valid values: ONCE_PER_EVENT, ONCE_PER_SESSION, or COUNTING_METHOD_UNSPECIFIED.
### Response
```json
{
"$defs": {
"KeyEventResource": {
"additionalProperties": false,
"description": "A GA4 key event resource (admin API).",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"event_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Event Name"
},
"counting_method": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Counting Method"
},
"create_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Create Time"
},
"deletable": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Deletable"
},
"custom": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Custom"
}
},
"title": "KeyEventResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"key_event": {
"anyOf": [
{
"$ref": "#/$defs/KeyEventResource"
},
{
"type": "null"
}
],
"default": null
},
"raw": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Raw"
}
},
"required": [
"success"
],
"title": "CreateKeyEventOutput",
"type": "object"
}
```
### Parameters
ID of the Universal Analytics view to query. Found in the legacy Google Analytics Admin UI under View Settings.
Start date in YYYY-MM-DD format.
End date in YYYY-MM-DD format.
List of metric expression strings (each becomes a {expression: <metric>} entry), e.g. ['ga:sessions', 'ga:pageviews'].
Optional list of dimension name strings (each becomes a {name: <dimension>} entry), e.g. ['ga:country', 'ga:browser'].
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"reports": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Reports",
"type": "array"
},
"raw": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Raw"
}
},
"required": [
"success"
],
"title": "RunReportOutput",
"type": "object"
}
```
### Parameters
GA4 property identifier. Accepts either the bare numeric ID ('123456789') or the full resource path ('properties/123456789'); only the numeric ID is sent in the URL.
Start date in YYYY-MM-DD format.
End date in YYYY-MM-DD format.
List of metric name strings (each becomes a {name: <metric>} entry), e.g. ['activeUsers', 'screenPageViews'].
Optional list of dimension name strings (each becomes a {name: <dimension>} entry), e.g. ['country', 'deviceCategory'].
Optional GA4 FilterExpression object restricting which dimension values appear in the report. See the Google Analytics Data API v1 docs for the schema.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"row_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Row Count"
},
"dimension_headers": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Dimension Headers",
"type": "array"
},
"metric_headers": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Metric Headers",
"type": "array"
},
"rows": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Rows",
"type": "array"
},
"totals": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Totals",
"type": "array"
},
"raw": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Raw"
}
},
"required": [
"success"
],
"title": "RunReportInGa4Output",
"type": "object"
}
```
## Limits & Quotas
- **Admin API** — default quota is 1,200 requests per minute per project, with
a daily ceiling of 600,000 requests per project. See the
[Admin API quotas docs](https://developers.google.com/analytics/devguides/config/admin/v1/quotas)
for the per-method breakdown.
- **Data API** — quotas are tracked separately per property (core tokens,
realtime tokens, server errors). See the
[Data API quotas docs](https://developers.google.com/analytics/devguides/reporting/data/v1/quotas)
for the multi-token model and per-tier limits (Standard vs. Analytics 360).
- **Universal Analytics Reporting API v4** is included for backward
compatibility only; Universal Analytics properties stopped processing data on
July 1, 2024. `run_report` will return `success=False` with an API error
for any non-GA4 view.
- **Error model** — non-2xx HTTP responses and timeouts are caught and returned
as `success=False` plus a populated `error` string rather than raised. Plan
for agent-side retries based on the error string.
## Related integrations
## Links
- [Google Analytics](https://analytics.google.com)
---
# Google AppSheet Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-appsheet
Manage rows in Google AppSheet tables via the AppSheet API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_appsheet/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google AppSheet** to any ModuleX agent or workflow. Manage rows in Google AppSheet tables (add, read, update, delete) via the AppSheet REST API (`api.appsheet.com`).
**Categories**: Productivity & Collaboration · No Code · Databases · **Auth**: AppSheet API Key · **Actions**: 4
## Authentication
### AppSheet API Key
Authenticate using your AppSheet Application Access Key and App ID
Open your app in AppSheet at https://www.appsheet.com
Go to Settings > Integrations > IN: from cloud services to your app
Enable the API and copy the Application Access Key
Copy the App ID from the URL or Settings > App Info
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| App ID | Your AppSheet application ID (found in Settings > App Info or the app URL) | Yes | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
| Application Access Key | Your AppSheet Application Access Key from Settings > Integrations | Yes | `V2-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx` |
## Available Actions
### Parameters
Name of the table to add a row to
JSON object representing the row data to add, with keys matching table column names
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"rows": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Rows",
"type": "array"
}
},
"required": [
"success"
],
"title": "AddRowOutput",
"type": "object"
}
```
### Parameters
Name of the table to delete a row from
JSON object containing the key field values of the record to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"rows": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Rows",
"type": "array"
}
},
"required": [
"success"
],
"title": "DeleteRowOutput",
"type": "object"
}
```
### Parameters
Name of the table to read rows from
An expression to filter and format the rows returned, e.g. Filter(TableName, [Column] = "Value")
Filter results using key field values, e.g. {"First Name": "John"}
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"rows": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Rows",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetRowsOutput",
"type": "object"
}
```
### Parameters
Name of the table containing the row to update
JSON object with the key field values of the record to update and any fields to change
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"rows": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Rows",
"type": "array"
}
},
"required": [
"success"
],
"title": "UpdateRowOutput",
"type": "object"
}
```
## Limits & Quotas
- AppSheet API has no publicly documented per-minute rate limits, but Google
recommends keeping request volume moderate for shared-tenant apps.
- Each app must have the API enabled in Settings > Integrations.
- Error model: non-2xx responses and timeouts are caught and returned as
`success=False` + `error` rather than raising.
## Related integrations
## Links
- [Google AppSheet](https://www.appsheet.com)
---
# Google Calendar Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-calendar
Manage Google Calendar events, calendars, and availability via the Google Calendar v3 REST API.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_calendar/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google Calendar** to any ModuleX agent or workflow. Manage Google Calendar events, calendars, attendees, recurring series, and free/busy availability via the Google Calendar v3 REST API (`https://www.googleapis.com/calendar/v3`).
**Categories**: Scheduling & Events · Productivity & Collaboration · Scheduling · **Auth**: OAuth2 · **Actions**: 16
## Authentication
### OAuth2 Authentication
Connect using Google OAuth (recommended). Grants access to read and manage the user's calendars and events.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Google Cloud OAuth Client ID for the Calendar API. | Yes | `xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com` |
| Client Secret | Google Cloud OAuth Client Secret for the Calendar API. | Yes | `GOCSPX-xxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Scopes**: `https://www.googleapis.com/auth/calendar`, `https://www.googleapis.com/auth/calendar.events`
## Available Actions
### Parameters
Calendar identifier (use 'primary' for the user's primary calendar, or a calendar email/ID). (Default: `primary`)
ID of the event to update.
List of attendee email addresses to add (existing attendees are preserved).
Whether to send notifications about the update. One of: all, externalOnly, none.
### Response
```json
{
"$defs": {
"EventSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"htmlLink": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Htmllink"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"start": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Start"
},
"end": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "End"
},
"creator": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Creator"
},
"organizer": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Organizer"
},
"attendees": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Attendees",
"type": "array"
},
"recurrence": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Recurrence"
},
"recurringEventId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Recurringeventid"
},
"visibility": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Visibility"
},
"colorId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Colorid"
},
"conferenceData": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Conferencedata"
},
"hangoutLink": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hangoutlink"
},
"kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kind"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"iCalUID": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Icaluid"
},
"sequence": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Sequence"
},
"eventType": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Eventtype"
}
},
"title": "EventSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"event": {
"anyOf": [
{
"$ref": "#/$defs/EventSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "AddAttendeesToEventOutput",
"type": "object"
}
```
### Parameters
Calendar identifier (use 'primary' for the user's primary calendar, or a calendar email/ID). (Default: `primary`)
Event title.
Event start. For all-day events: yyyy-mm-dd. For timed events: RFC3339, e.g. 2025-01-15T10:00:00-05:00.
Event end. Same formats as event_start_date.
Event location.
Event description.
List of attendee email addresses.
Color ID for the event. See list_color_id_options for valid values.
IANA time zone name for the event (e.g. 'America/New_York'). Defaults to the calendar's time zone.
Whether to send invitations. One of: all, externalOnly, none.
Whether to attach a Google Meet conference link to this event. (Default: `false`)
Event visibility. One of: default, public, private, confidential.
Recurrence frequency. One of: DAILY, WEEKLY, MONTHLY, YEARLY.
Recurrence interval (1 = every period, 2 = every other, ...). Defaults to 1.
Two-letter day codes for WEEKLY recurrence (SU,MO,TU,WE,TH,FR,SA).
End date for recurrence (yyyy-mm-dd). Mutually exclusive with repeat_times.
Number of occurrences. Mutually exclusive with repeat_until.
### Response
```json
{
"$defs": {
"EventSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"htmlLink": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Htmllink"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"start": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Start"
},
"end": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "End"
},
"creator": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Creator"
},
"organizer": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Organizer"
},
"attendees": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Attendees",
"type": "array"
},
"recurrence": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Recurrence"
},
"recurringEventId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Recurringeventid"
},
"visibility": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Visibility"
},
"colorId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Colorid"
},
"conferenceData": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Conferencedata"
},
"hangoutLink": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hangoutlink"
},
"kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kind"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"iCalUID": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Icaluid"
},
"sequence": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Sequence"
},
"eventType": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Eventtype"
}
},
"title": "EventSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"event": {
"anyOf": [
{
"$ref": "#/$defs/EventSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateEventOutput",
"type": "object"
}
```
### Parameters
Calendar identifier (use 'primary' for the user's primary calendar). (Default: `primary`)
ID of the event to delete.
Whether to send cancellation notifications. One of: all, externalOnly, none.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"eventId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Eventid"
},
"statusCode": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Statuscode"
}
},
"required": [
"success"
],
"title": "DeleteEventOutput",
"type": "object"
}
```
### Parameters
Calendar identifier (use 'primary' for the user's primary calendar). (Default: `primary`)
### Response
```json
{
"$defs": {
"CalendarSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location"
},
"timeZone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timezone"
},
"kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kind"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"accessRole": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Accessrole"
},
"primary": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Primary"
},
"selected": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Selected"
},
"backgroundColor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Backgroundcolor"
},
"foregroundColor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Foregroundcolor"
},
"colorId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Colorid"
},
"hidden": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Hidden"
}
},
"title": "CalendarSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"calendar": {
"anyOf": [
{
"$ref": "#/$defs/CalendarSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetCalendarOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"CalendarSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location"
},
"timeZone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timezone"
},
"kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kind"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"accessRole": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Accessrole"
},
"primary": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Primary"
},
"selected": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Selected"
},
"backgroundColor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Backgroundcolor"
},
"foregroundColor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Foregroundcolor"
},
"colorId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Colorid"
},
"hidden": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Hidden"
}
},
"title": "CalendarSummary",
"type": "object"
},
"SettingItem": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"value": {
"anyOf": [
{},
{
"type": "null"
}
],
"default": null,
"title": "Value"
},
"kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kind"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
}
},
"title": "SettingItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"primaryCalendar": {
"anyOf": [
{
"$ref": "#/$defs/CalendarSummary"
},
{
"type": "null"
}
],
"default": null
},
"calendars": {
"items": {
"$ref": "#/$defs/CalendarSummary"
},
"title": "Calendars",
"type": "array"
},
"settings": {
"items": {
"$ref": "#/$defs/SettingItem"
},
"title": "Settings",
"type": "array"
},
"timezone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timezone"
},
"locale": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Locale"
},
"colors": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Colors"
}
},
"required": [
"success"
],
"title": "GetCurrentUserOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Date"
},
"time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Time"
},
"timezone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timezone"
},
"timezoneOffset": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timezoneoffset"
},
"timestamp": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp"
},
"isoString": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Isostring"
},
"rfc3339": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rfc3339"
}
},
"required": [
"success"
],
"title": "GetDateTimeOutput",
"type": "object"
}
```
### Parameters
Calendar identifier (use 'primary' for the user's primary calendar). (Default: `primary`)
ID of the event to retrieve.
### Response
```json
{
"$defs": {
"EventSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"htmlLink": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Htmllink"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"start": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Start"
},
"end": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "End"
},
"creator": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Creator"
},
"organizer": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Organizer"
},
"attendees": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Attendees",
"type": "array"
},
"recurrence": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Recurrence"
},
"recurringEventId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Recurringeventid"
},
"visibility": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Visibility"
},
"colorId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Colorid"
},
"conferenceData": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Conferencedata"
},
"hangoutLink": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hangoutlink"
},
"kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kind"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"iCalUID": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Icaluid"
},
"sequence": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Sequence"
},
"eventType": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Eventtype"
}
},
"title": "EventSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"event": {
"anyOf": [
{
"$ref": "#/$defs/EventSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetEventOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"CalendarSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location"
},
"timeZone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timezone"
},
"kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kind"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"accessRole": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Accessrole"
},
"primary": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Primary"
},
"selected": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Selected"
},
"backgroundColor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Backgroundcolor"
},
"foregroundColor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Foregroundcolor"
},
"colorId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Colorid"
},
"hidden": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Hidden"
}
},
"title": "CalendarSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"calendars": {
"items": {
"$ref": "#/$defs/CalendarSummary"
},
"title": "Calendars",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListCalendarsOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"ColorEntry": {
"additionalProperties": false,
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Label"
},
"value": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
}
},
"title": "ColorEntry",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"options": {
"items": {
"$ref": "#/$defs/ColorEntry"
},
"title": "Options",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListColorIdOptionsOutput",
"type": "object"
}
```
### Parameters
Calendar identifier (use 'primary' for the user's primary calendar). (Default: `primary`)
ID of the recurring event.
Maximum attendees per instance to include.
Maximum number of instances to return across paged calls.
Include cancelled instances.
Lower bound (RFC3339) for instance start times.
Upper bound (RFC3339) for instance start times.
IANA time zone used in the response.
### Response
```json
{
"$defs": {
"EventSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"htmlLink": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Htmllink"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"start": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Start"
},
"end": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "End"
},
"creator": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Creator"
},
"organizer": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Organizer"
},
"attendees": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Attendees",
"type": "array"
},
"recurrence": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Recurrence"
},
"recurringEventId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Recurringeventid"
},
"visibility": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Visibility"
},
"colorId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Colorid"
},
"conferenceData": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Conferencedata"
},
"hangoutLink": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hangoutlink"
},
"kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kind"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"iCalUID": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Icaluid"
},
"sequence": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Sequence"
},
"eventType": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Eventtype"
}
},
"title": "EventSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"instances": {
"items": {
"$ref": "#/$defs/EventSummary"
},
"title": "Instances",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListEventInstancesOutput",
"type": "object"
}
```
### Parameters
Calendar identifier (use 'primary' for the user's primary calendar). (Default: `primary`)
Specifies an iCalendar UID to filter by.
Maximum attendees per event to include.
Maximum number of events to return across paged calls.
Sort order. One of: startTime, updated. startTime requires single_events=true.
propertyName=value constraint on private extended properties.
Free-text search across event fields.
propertyName=value constraint on shared extended properties.
Include cancelled events.
Include hidden invitations.
Expand recurring events into individual instances.
Upper bound (RFC3339) for event start times.
Lower bound (RFC3339) for event start times.
IANA time zone used in the response.
Lower bound (RFC3339) for event last-modified time.
Filter by event type. Values: default, focusTime, outOfOffice, workingLocation.
### Response
```json
{
"$defs": {
"EventSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"htmlLink": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Htmllink"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"start": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Start"
},
"end": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "End"
},
"creator": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Creator"
},
"organizer": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Organizer"
},
"attendees": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Attendees",
"type": "array"
},
"recurrence": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Recurrence"
},
"recurringEventId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Recurringeventid"
},
"visibility": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Visibility"
},
"colorId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Colorid"
},
"conferenceData": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Conferencedata"
},
"hangoutLink": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hangoutlink"
},
"kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kind"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"iCalUID": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Icaluid"
},
"sequence": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Sequence"
},
"eventType": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Eventtype"
}
},
"title": "EventSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"events": {
"items": {
"$ref": "#/$defs/EventSummary"
},
"title": "Events",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListEventsOutput",
"type": "object"
}
```
### Parameters
List of calendar IDs to query (use 'primary' for the user's primary calendar). (Default: `["primary"]`)
Start of the query window (RFC3339).
End of the query window (RFC3339).
IANA time zone for the response.
### Response
```json
{
"$defs": {
"FreeBusyCalendar": {
"additionalProperties": false,
"properties": {
"busy": {
"items": {
"$ref": "#/$defs/FreeBusyPeriod"
},
"title": "Busy",
"type": "array"
},
"errors": {
"anyOf": [
{
"items": {
"additionalProperties": true,
"type": "object"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Errors"
}
},
"title": "FreeBusyCalendar",
"type": "object"
},
"FreeBusyPeriod": {
"additionalProperties": false,
"properties": {
"start": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Start"
},
"end": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "End"
}
},
"title": "FreeBusyPeriod",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"timeMin": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timemin"
},
"timeMax": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timemax"
},
"calendars": {
"additionalProperties": {
"$ref": "#/$defs/FreeBusyCalendar"
},
"title": "Calendars",
"type": "object"
}
},
"required": [
"success"
],
"title": "QueryFreeBusyCalendarsOutput",
"type": "object"
}
```
### Parameters
Calendar identifier (use 'primary' for the user's primary calendar). (Default: `primary`)
Natural-language event description, e.g. 'Meet with Sarah at 3pm Friday'.
Optional list of attendee email addresses to add after parsing.
### Response
```json
{
"$defs": {
"EventSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"htmlLink": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Htmllink"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"start": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Start"
},
"end": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "End"
},
"creator": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Creator"
},
"organizer": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Organizer"
},
"attendees": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Attendees",
"type": "array"
},
"recurrence": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Recurrence"
},
"recurringEventId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Recurringeventid"
},
"visibility": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Visibility"
},
"colorId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Colorid"
},
"conferenceData": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Conferencedata"
},
"hangoutLink": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hangoutlink"
},
"kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kind"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"iCalUID": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Icaluid"
},
"sequence": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Sequence"
},
"eventType": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Eventtype"
}
},
"title": "EventSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"event": {
"anyOf": [
{
"$ref": "#/$defs/EventSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "QuickAddEventOutput",
"type": "object"
}
```
### Parameters
Calendar identifier (use 'primary' for the user's primary calendar). (Default: `primary`)
ID of the event to update.
New event title.
New start (yyyy-mm-dd for all-day, or RFC3339 for timed).
New end (yyyy-mm-dd for all-day, or RFC3339 for timed).
New event location.
New event description.
Replacement list of attendee email addresses.
New color ID for the event.
IANA time zone (defaults to the event's existing time zone).
Whether to send notifications. One of: all, externalOnly, none.
Updated recurrence frequency. One of: DAILY, WEEKLY, MONTHLY, YEARLY.
Updated recurrence interval.
Two-letter day codes for WEEKLY recurrence.
New end date for recurrence (yyyy-mm-dd).
New number of occurrences.
### Response
```json
{
"$defs": {
"EventSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"htmlLink": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Htmllink"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"start": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Start"
},
"end": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "End"
},
"creator": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Creator"
},
"organizer": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Organizer"
},
"attendees": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Attendees",
"type": "array"
},
"recurrence": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Recurrence"
},
"recurringEventId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Recurringeventid"
},
"visibility": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Visibility"
},
"colorId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Colorid"
},
"conferenceData": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Conferencedata"
},
"hangoutLink": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hangoutlink"
},
"kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kind"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"iCalUID": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Icaluid"
},
"sequence": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Sequence"
},
"eventType": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Eventtype"
}
},
"title": "EventSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"event": {
"anyOf": [
{
"$ref": "#/$defs/EventSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UpdateEventOutput",
"type": "object"
}
```
### Parameters
Calendar identifier (use 'primary' for the user's primary calendar). (Default: `primary`)
ID of the specific recurring-event instance to update.
New event title.
New start (yyyy-mm-dd for all-day, or RFC3339 for timed).
New end (yyyy-mm-dd for all-day, or RFC3339 for timed).
New event location.
New event description.
Replacement list of attendee email addresses.
New color ID for the event instance.
IANA time zone (defaults to the instance's existing time zone).
Whether to send notifications. One of: all, externalOnly, none.
### Response
```json
{
"$defs": {
"EventSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"htmlLink": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Htmllink"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"start": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Start"
},
"end": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "End"
},
"creator": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Creator"
},
"organizer": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Organizer"
},
"attendees": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Attendees",
"type": "array"
},
"recurrence": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Recurrence"
},
"recurringEventId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Recurringeventid"
},
"visibility": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Visibility"
},
"colorId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Colorid"
},
"conferenceData": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Conferencedata"
},
"hangoutLink": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hangoutlink"
},
"kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kind"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"iCalUID": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Icaluid"
},
"sequence": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Sequence"
},
"eventType": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Eventtype"
}
},
"title": "EventSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"event": {
"anyOf": [
{
"$ref": "#/$defs/EventSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UpdateEventInstanceOutput",
"type": "object"
}
```
### Parameters
Calendar identifier (use 'primary' for the user's primary calendar). (Default: `primary`)
ID of the parent recurring event.
ID of the instance from which the split begins (this and all following instances are updated).
New event title for the split series.
New start (yyyy-mm-dd or RFC3339) for the split series.
New end (yyyy-mm-dd or RFC3339) for the split series.
New location for the split series.
New description for the split series.
Replacement list of attendee email addresses.
New color ID for the split series.
IANA time zone for the split series.
Whether to send notifications. One of: all, externalOnly, none.
Optional new recurrence frequency for the split series.
Optional new recurrence interval for the split series.
Optional new recurrence end date (yyyy-mm-dd).
Optional new occurrence count.
### Response
```json
{
"$defs": {
"EventSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"htmlLink": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Htmllink"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"start": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Start"
},
"end": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "End"
},
"creator": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Creator"
},
"organizer": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Organizer"
},
"attendees": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Attendees",
"type": "array"
},
"recurrence": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Recurrence"
},
"recurringEventId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Recurringeventid"
},
"visibility": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Visibility"
},
"colorId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Colorid"
},
"conferenceData": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Conferencedata"
},
"hangoutLink": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hangoutlink"
},
"kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kind"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"iCalUID": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Icaluid"
},
"sequence": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Sequence"
},
"eventType": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Eventtype"
}
},
"title": "EventSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"originalEventId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Originaleventid"
},
"newEvent": {
"anyOf": [
{
"$ref": "#/$defs/EventSummary"
},
{
"type": "null"
}
],
"default": null
},
"trimmedRecurrence": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Trimmedrecurrence"
}
},
"required": [
"success"
],
"title": "UpdateFollowingInstancesOutput",
"type": "object"
}
```
## Limits & Quotas
- Per-user default quota: ~1,000,000 queries/day; per-user per-100-seconds quota also applies (see [Google Calendar API quotas](https://developers.google.com/calendar/api/guides/quota)).
- Quotas are shared across all Google Calendar API methods for the authenticated user.
- `list_events` and `list_event_instances` page through results internally and honor `max_results` as a soft cap across pages.
- `update_following_instances` performs four sequential API calls (get original, get instance, delete instance, trim recurrence, create new event); on partial failure the deleted instance is restored automatically when possible. Network or quota errors mid-flow can leave the series in a manually-recoverable state.
- Error model: non-2xx responses raise (Pattern A). The runtime surfaces them as failed tool calls; the agent decides whether to retry.
## Related integrations
## Links
- [Google Calendar](https://calendar.google.com)
---
# Google Cloud Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-cloud
Google Cloud Platform services including Cloud Storage, BigQuery, Compute Engine, and Cloud Logging
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_cloud/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google Cloud** to any ModuleX agent or workflow. Google Cloud Platform integration providing Cloud Storage bucket and object management, BigQuery query execution and streaming inserts, BigQuery Data Transfer scheduled queries, Compute Engine instance control, and Cloud Logging via the GCP REST APIs.
**Categories**: Cloud Infrastructure · Data & Analytics · Developer Tools & Infrastructure · **Auth**: Service Account Key · **Actions**: 11
## Authentication
### Service Account Key
Authenticate using a GCP service account JSON key file
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Service Account Key JSON | The full JSON content of your GCP service account key file | Yes | `{"type":"service_account","project_id":"...","private_key":"...","client_email":"..."}` |
## Available Actions
### Parameters
Globally unique bucket name
Bucket location (e.g. US, EU, us-central1). Defaults to US (Default: `US`)
Storage class: STANDARD, NEARLINE, COLDLINE, or ARCHIVE (Default: `STANDARD`)
### Response
```json
{
"$defs": {
"BucketMetadata": {
"additionalProperties": false,
"description": "Metadata for a Google Cloud Storage bucket.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location"
},
"storage_class": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Storage Class"
},
"time_created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Time Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"project_number": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Project Number"
}
},
"title": "BucketMetadata",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"bucket": {
"anyOf": [
{
"$ref": "#/$defs/BucketMetadata"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateBucketOutput",
"type": "object"
}
```
### Parameters
Name of the bucket
### Response
```json
{
"$defs": {
"BucketMetadata": {
"additionalProperties": false,
"description": "Metadata for a Google Cloud Storage bucket.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location"
},
"storage_class": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Storage Class"
},
"time_created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Time Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"project_number": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Project Number"
}
},
"title": "BucketMetadata",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"bucket": {
"anyOf": [
{
"$ref": "#/$defs/BucketMetadata"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetBucketOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"BucketMetadata": {
"additionalProperties": false,
"description": "Metadata for a Google Cloud Storage bucket.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location"
},
"storage_class": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Storage Class"
},
"time_created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Time Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"project_number": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Project Number"
}
},
"title": "BucketMetadata",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"buckets": {
"items": {
"$ref": "#/$defs/BucketMetadata"
},
"title": "Buckets",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListBucketsOutput",
"type": "object"
}
```
### Parameters
Name of the bucket to search
Object name prefix to filter by
Delimiter for directory-like listing (commonly '/')
### Response
```json
{
"$defs": {
"ObjectMetadata": {
"additionalProperties": false,
"description": "Metadata for a Google Cloud Storage object.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"bucket": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Bucket"
},
"size": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"content_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Type"
},
"time_created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Time Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"md5_hash": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Md5 Hash"
}
},
"title": "ObjectMetadata",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"objects": {
"items": {
"$ref": "#/$defs/ObjectMetadata"
},
"title": "Objects",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchObjectsOutput",
"type": "object"
}
```
### Parameters
Name of the bucket containing the object
Full path/name of the object in the bucket
### Response
```json
{
"$defs": {
"ObjectMetadata": {
"additionalProperties": false,
"description": "Metadata for a Google Cloud Storage object.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"bucket": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Bucket"
},
"size": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"content_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Type"
},
"time_created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Time Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"md5_hash": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Md5 Hash"
}
},
"title": "ObjectMetadata",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"metadata": {
"anyOf": [
{
"$ref": "#/$defs/ObjectMetadata"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetObjectOutput",
"type": "object"
}
```
### Parameters
Name of the destination bucket
Destination path/name for the object in the bucket
Text content to upload
MIME type of the content (e.g. text/plain, application/json) (Default: `text/plain`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"object_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Object Name"
},
"bucket": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Bucket"
}
},
"required": [
"success"
],
"title": "UploadObjectOutput",
"type": "object"
}
```
### Parameters
Name of the log to write to
Log message text
Log severity: DEFAULT, DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, or EMERGENCY (Default: `DEFAULT`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "LoggingWriteLogOutput",
"type": "object"
}
```
### Parameters
GoogleSQL query to execute
Dataset location (e.g. US, EU). Must match dataset location (Default: `US`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"rows": {
"items": {
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"type": "object"
},
"title": "Rows",
"type": "array"
},
"total_rows": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Rows"
}
},
"required": [
"success"
],
"title": "RunQueryOutput",
"type": "object"
}
```
### Parameters
BigQuery dataset ID
BigQuery table ID
Array of row objects to insert, each with column names as keys
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"inserted_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Inserted Count"
}
},
"required": [
"success"
],
"title": "BigqueryInsertRowsOutput",
"type": "object"
}
```
### Parameters
Destination dataset ID for query results
Human-readable name for the scheduled query
GoogleSQL query to schedule
Geographic location of the dataset (e.g. us, eu) (Default: `us`)
Schedule in cron-like format (e.g. 'every 24 hours', '1st monday of month 09:00')
Write behavior: WRITE_TRUNCATE or WRITE_APPEND (Default: `WRITE_TRUNCATE`)
Destination table name template, can use {run_date} or {run_time} variables (Default: `logs`)
### Response
```json
{
"$defs": {
"TransferConfig": {
"additionalProperties": false,
"description": "A BigQuery Data Transfer scheduled query config.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"data_source_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Data Source Id"
},
"schedule": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Schedule"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"destination_dataset_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Destination Dataset Id"
}
},
"title": "TransferConfig",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"transfer_config": {
"anyOf": [
{
"$ref": "#/$defs/TransferConfig"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateScheduledQueryOutput",
"type": "object"
}
```
### Parameters
Compute Engine zone (e.g. us-central1-a)
Name of the VM instance
Action to perform: start or stop
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"operation_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Operation Name"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
}
},
"required": [
"success"
],
"title": "SwitchInstanceBootStatusOutput",
"type": "object"
}
```
## Limits & Quotas
- **Cloud Storage**: 1,000 bucket creates per project per 2 seconds; 5,000 object mutations per bucket per second.
- **BigQuery**: 100 concurrent queries per project; streaming inserts limited to 50,000 rows per request and 10 MB per request.
- **Compute Engine**: API rate limits vary by method (typically 20 requests/second per project per region).
- **Cloud Logging**: 60 write requests per second per project.
- **Error model**: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Google Cloud](https://cloud.google.com)
---
# Google Contacts Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-contacts
Manage Google People (Contacts) — create, list, get, update, and delete contacts plus list Google Workspace directory people.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_contacts/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google Contacts** to any ModuleX agent or workflow. Manage Google Contacts (People API v1) — create, list, get, update, and delete the authenticated user's contacts, plus list Google Workspace directory people. All calls go to `https://people.googleapis.com/v1`.
**Categories**: Productivity & Collaboration · CRM · **Auth**: Google OAuth2 · **Actions**: 6
## Authentication
### Google OAuth2
Connect using Google OAuth (recommended) — Contacts + Directory scopes.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Google Cloud OAuth 2.0 Client ID. | Yes | `xxxxxxxxxxxx-xxxxxxxxxxxxxxxx.apps.googleusercontent.com` |
| Client Secret | Google Cloud OAuth 2.0 Client Secret. | Yes | `GOCSPX-xxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Scopes**: `https://www.googleapis.com/auth/contacts`, `https://www.googleapis.com/auth/directory.readonly`
## Available Actions
### Parameters
Contact fields to populate and return — any of: names, emailAddresses, phoneNumbers, addresses, biographies, birthdays, calendarUrls, genders, urls.
Contact's first name (used when person_fields includes 'names').
Contact's middle name (used when person_fields includes 'names').
Contact's last name (used when person_fields includes 'names').
Contact's email address (used when person_fields includes 'emailAddresses').
Contact's phone number (used when person_fields includes 'phoneNumbers').
Street address (used when person_fields includes 'addresses').
City (used when person_fields includes 'addresses').
State / region (used when person_fields includes 'addresses').
Postal / zip code (used when person_fields includes 'addresses').
Country (used when person_fields includes 'addresses').
Biography text (used when person_fields includes 'biographies').
Birthday in YYYY-MM-DD format (used when person_fields includes 'birthdays').
Calendar URL (used when person_fields includes 'calendarUrls').
Gender: male, female, or unspecified (used when person_fields includes 'genders').
List of associated URLs (used when person_fields includes 'urls').
Optional extra fields merged into the Person request body. See https://developers.google.com/people/api/rest/v1/people for the full schema.
### Response
```json
{
"$defs": {
"ContactSummary": {
"additionalProperties": false,
"description": "A Google People `Person` resource, projected to the fields most tools read.",
"properties": {
"resource_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Resource Name"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"given_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Given Name"
},
"family_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Family Name"
},
"middle_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Middle Name"
},
"email_addresses": {
"items": {
"type": "string"
},
"title": "Email Addresses",
"type": "array"
},
"phone_numbers": {
"items": {
"type": "string"
},
"title": "Phone Numbers",
"type": "array"
},
"organizations": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Organizations",
"type": "array"
},
"addresses": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Addresses",
"type": "array"
},
"biographies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Biographies",
"type": "array"
},
"urls": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Urls",
"type": "array"
},
"birthdays": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Birthdays",
"type": "array"
},
"genders": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Genders",
"type": "array"
},
"raw": {
"additionalProperties": true,
"description": "Untouched upstream Person object — all fields requested via personFields.",
"title": "Raw",
"type": "object"
}
},
"title": "ContactSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"contact": {
"anyOf": [
{
"$ref": "#/$defs/ContactSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateContactOutput",
"type": "object"
}
```
### Parameters
The People API resource name identifying the contact, e.g. 'people/c123456789'.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"resource_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Resource Name"
}
},
"required": [
"success"
],
"title": "DeleteContactOutput",
"type": "object"
}
```
### Parameters
The People API resource name identifying the contact, e.g. 'people/c123456789'.
Contact fields to return — any of: addresses, ageRanges, biographies, birthdays, calendarUrls, clientData, coverPhotos, emailAddresses, events, externalIds, genders, imClients, interests, locales, locations, memberships, metadata, miscKeywords, names, nicknames, occupations, organizations, phoneNumbers, photos, relations, sipAddresses, skills, urls, userDefined.
### Response
```json
{
"$defs": {
"ContactSummary": {
"additionalProperties": false,
"description": "A Google People `Person` resource, projected to the fields most tools read.",
"properties": {
"resource_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Resource Name"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"given_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Given Name"
},
"family_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Family Name"
},
"middle_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Middle Name"
},
"email_addresses": {
"items": {
"type": "string"
},
"title": "Email Addresses",
"type": "array"
},
"phone_numbers": {
"items": {
"type": "string"
},
"title": "Phone Numbers",
"type": "array"
},
"organizations": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Organizations",
"type": "array"
},
"addresses": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Addresses",
"type": "array"
},
"biographies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Biographies",
"type": "array"
},
"urls": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Urls",
"type": "array"
},
"birthdays": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Birthdays",
"type": "array"
},
"genders": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Genders",
"type": "array"
},
"raw": {
"additionalProperties": true,
"description": "Untouched upstream Person object — all fields requested via personFields.",
"title": "Raw",
"type": "object"
}
},
"title": "ContactSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"contact": {
"anyOf": [
{
"$ref": "#/$defs/ContactSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetContactOutput",
"type": "object"
}
```
### Parameters
Contact fields to return on every result — same enum as get_contact's `fields`.
Maximum number of pages to fetch (1-500). Prevents runaway pagination. (Default: `50`)
### Response
```json
{
"$defs": {
"ContactSummary": {
"additionalProperties": false,
"description": "A Google People `Person` resource, projected to the fields most tools read.",
"properties": {
"resource_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Resource Name"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"given_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Given Name"
},
"family_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Family Name"
},
"middle_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Middle Name"
},
"email_addresses": {
"items": {
"type": "string"
},
"title": "Email Addresses",
"type": "array"
},
"phone_numbers": {
"items": {
"type": "string"
},
"title": "Phone Numbers",
"type": "array"
},
"organizations": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Organizations",
"type": "array"
},
"addresses": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Addresses",
"type": "array"
},
"biographies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Biographies",
"type": "array"
},
"urls": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Urls",
"type": "array"
},
"birthdays": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Birthdays",
"type": "array"
},
"genders": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Genders",
"type": "array"
},
"raw": {
"additionalProperties": true,
"description": "Untouched upstream Person object — all fields requested via personFields.",
"title": "Raw",
"type": "object"
}
},
"title": "ContactSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"contacts": {
"items": {
"$ref": "#/$defs/ContactSummary"
},
"title": "Contacts",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListContactsOutput",
"type": "object"
}
```
### Parameters
Contact fields to return — same enum as get_contact's `fields`.
Directory source to return: 'DIRECTORY_SOURCE_TYPE_DOMAIN_CONTACT' or 'DIRECTORY_SOURCE_TYPE_DOMAIN_PROFILE'.
Optional. Additional sources to merge in via verified join keys. Any of: 'DIRECTORY_MERGE_SOURCE_TYPE_UNSPECIFIED', 'DIRECTORY_MERGE_SOURCE_TYPE_CONTACT'.
Number of people per response page (1-1000). Defaults to 100. (Default: `100`)
Page token returned from a previous response's nextPageToken.
Whether the response should include a nextSyncToken for incremental sync. (Default: `false`)
Sync token from a previous response — fetch only resources changed since then.
### Response
```json
{
"$defs": {
"ContactSummary": {
"additionalProperties": false,
"description": "A Google People `Person` resource, projected to the fields most tools read.",
"properties": {
"resource_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Resource Name"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"given_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Given Name"
},
"family_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Family Name"
},
"middle_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Middle Name"
},
"email_addresses": {
"items": {
"type": "string"
},
"title": "Email Addresses",
"type": "array"
},
"phone_numbers": {
"items": {
"type": "string"
},
"title": "Phone Numbers",
"type": "array"
},
"organizations": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Organizations",
"type": "array"
},
"addresses": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Addresses",
"type": "array"
},
"biographies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Biographies",
"type": "array"
},
"urls": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Urls",
"type": "array"
},
"birthdays": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Birthdays",
"type": "array"
},
"genders": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Genders",
"type": "array"
},
"raw": {
"additionalProperties": true,
"description": "Untouched upstream Person object — all fields requested via personFields.",
"title": "Raw",
"type": "object"
}
},
"title": "ContactSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"people": {
"items": {
"$ref": "#/$defs/ContactSummary"
},
"title": "People",
"type": "array"
},
"next_page_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page Token"
},
"next_sync_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Sync Token"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListDirectoryContactsOutput",
"type": "object"
}
```
### Parameters
The People API resource name identifying the contact to update.
Contact sections to update — any of: names, emailAddresses, phoneNumbers, addresses, biographies, birthdays, calendarUrls, genders, urls.
Updated first name (used when update_person_fields includes 'names').
Updated middle name (used when update_person_fields includes 'names').
Updated last name (used when update_person_fields includes 'names').
Updated email (used when update_person_fields includes 'emailAddresses').
Updated phone (used when update_person_fields includes 'phoneNumbers').
Updated street address (used when update_person_fields includes 'addresses').
Updated city.
Updated state / region.
Updated postal / zip code.
Updated country.
Updated biography.
Updated birthday in YYYY-MM-DD format.
Updated calendar URL.
Updated gender: male, female, or unspecified.
Updated list of associated URLs.
Optional extra fields merged into the Person request body. See https://developers.google.com/people/api/rest/v1/people for the full schema.
### Response
```json
{
"$defs": {
"ContactSummary": {
"additionalProperties": false,
"description": "A Google People `Person` resource, projected to the fields most tools read.",
"properties": {
"resource_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Resource Name"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"given_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Given Name"
},
"family_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Family Name"
},
"middle_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Middle Name"
},
"email_addresses": {
"items": {
"type": "string"
},
"title": "Email Addresses",
"type": "array"
},
"phone_numbers": {
"items": {
"type": "string"
},
"title": "Phone Numbers",
"type": "array"
},
"organizations": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Organizations",
"type": "array"
},
"addresses": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Addresses",
"type": "array"
},
"biographies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Biographies",
"type": "array"
},
"urls": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Urls",
"type": "array"
},
"birthdays": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Birthdays",
"type": "array"
},
"genders": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Genders",
"type": "array"
},
"raw": {
"additionalProperties": true,
"description": "Untouched upstream Person object — all fields requested via personFields.",
"title": "Raw",
"type": "object"
}
},
"title": "ContactSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"contact": {
"anyOf": [
{
"$ref": "#/$defs/ContactSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UpdateContactOutput",
"type": "object"
}
```
## Limits & Quotas
- Google People API default quota: **90 reads/minute** and
**60 writes/minute** per user, **1,200 reads/minute** per project. Higher
limits available via Google Cloud quota request.
- `list_contacts` auto-paginates through `people/me/connections` — beware large
contact directories (each page is 100 contacts by default; the implementation
fetches every page in sequence).
- `list_directory_contacts` returns one page per call; supply `page_token` /
`sync_token` from a previous response for pagination or incremental sync.
- `update_contact` performs an extra `GET` to refresh the etag before the
`PATCH`. Stale-etag updates are rejected by Google with HTTP 400.
- **Error model**: non-2xx responses raise `httpx.HTTPStatusError`. The
modulex runtime surfaces these as failed tool calls — plan for retries on the
agent side if a transient 5xx is possible.
## Related integrations
## Links
- [Google Contacts](https://contacts.google.com)
---
# Google Docs Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-docs
Create, read, and edit Google Docs documents via the Google Docs API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_docs/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google Docs** to any ModuleX agent or workflow. Create, read, and edit Google Docs documents via the Google Docs API (`docs.googleapis.com/v1`).
**Categories**: Productivity & Collaboration · Google Workspace · Documents · **Auth**: OAuth2 · **Actions**: 10
## Authentication
### OAuth2 Authentication
Connect using Google OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Google OAuth App Client ID | Yes | `xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com` |
| Client Secret | Google OAuth App Client Secret | Yes | `GOCSPX-xxxxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Scopes**: `https://www.googleapis.com/auth/documents`
## Available Actions
### Parameters
The ID of the document to append the image to
The URL of the image to insert into the document
Whether to append at the beginning (true) or end (false) of the document (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"document_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Document Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
}
},
"required": [
"success"
],
"title": "AppendImageOutput",
"type": "object"
}
```
### Parameters
The ID of the document to append text to
The text to append to the document
Whether to append at the beginning (true) or end (false) of the document (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"document_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Document Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
}
},
"required": [
"success"
],
"title": "AppendTextOutput",
"type": "object"
}
```
### Parameters
Title of the new document
Text content to insert into the document
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"document_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Document Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
}
},
"required": [
"success"
],
"title": "CreateDocumentOutput",
"type": "object"
}
```
### Parameters
The ID of the document to retrieve
Whether to populate the tabs field instead of the body field (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"document_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Document Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"body": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Body"
}
},
"required": [
"success"
],
"title": "GetDocumentOutput",
"type": "object"
}
```
### Parameters
The ID of the document
List of tab IDs to retrieve content for (element type: string)
### Response
```json
{
"$defs": {
"TabContent": {
"additionalProperties": false,
"description": "Tab content returned by get_tab_content.",
"properties": {
"tab_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Tab Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"body": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Body"
}
},
"title": "TabContent",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"tabs": {
"items": {
"$ref": "#/$defs/TabContent"
},
"title": "Tabs",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetTabContentOutput",
"type": "object"
}
```
### Parameters
The ID of the document
The index position to insert the page break at (Default: `1`)
The tab ID to insert the page break into
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"document_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Document Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
}
},
"required": [
"success"
],
"title": "InsertPageBreakOutput",
"type": "object"
}
```
### Parameters
The ID of the document
The number of rows in the table
The number of columns in the table
The index position to insert the table at (Default: `1`)
The tab ID to insert the table into
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"document_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Document Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
}
},
"required": [
"success"
],
"title": "InsertTableOutput",
"type": "object"
}
```
### Parameters
The ID of the document
The text to insert
The index position to insert the text at (Default: `1`)
The tab ID to insert the text into
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"document_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Document Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
}
},
"required": [
"success"
],
"title": "InsertTextOutput",
"type": "object"
}
```
### Parameters
The ID of the document
The ID of the image to be replaced (from the document's inlineObjects)
The URL of the new image to replace with
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"document_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Document Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
}
},
"required": [
"success"
],
"title": "ReplaceImageOutput",
"type": "object"
}
```
### Parameters
The ID of the document
The text to find and replace
The replacement text
Whether the search is case-sensitive (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"document_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Document Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
}
},
"required": [
"success"
],
"title": "ReplaceTextOutput",
"type": "object"
}
```
## Limits & Quotas
- Google Docs API: 300 read requests per minute per user, 60 write requests per minute per user.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Google Docs](https://docs.google.com)
---
# Google Drive Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-drive
Google Workspace integration: Drive (files/folders), Docs, Sheets, and Slides via the v3 / v1 REST APIs.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_drive/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google Drive** to any ModuleX agent or workflow. Google Workspace integration via the v3 (Drive) / v1 (Docs, Slides) / v4 (Sheets) REST APIs. Pure HTTP, no SDK dep. 16 actions.
**Categories**: Cloud Infrastructure · File Storage · Document Management · Productivity · **Auth**: OAuth2, Service Account / Access Token · **Actions**: 16
## Authentication
### OAuth2 Authentication
Connect using Google OAuth2 (recommended). Provides secure access to Drive, Docs, Sheets, and Slides.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Google OAuth2 Client ID from Cloud Console | Yes | `123456789-xxxxxxxxxxxxxxxx.apps.googleusercontent.com` |
| Client Secret | Google OAuth2 Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Scopes**: `https://www.googleapis.com/auth/drive.file`, `https://www.googleapis.com/auth/documents`, `https://www.googleapis.com/auth/spreadsheets`, `https://www.googleapis.com/auth/presentations`
### Service Account / Access Token
Use a pre-generated access token or service account credentials
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Access Token | A valid Google OAuth2 access token | Yes | `-` |
## Available Actions
### Parameters
File name (must end with .txt or .md)
Text content
Parent folder (defaults to root)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"mime_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mime Type"
},
"web_view_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web View Link"
}
},
"required": [
"success"
],
"title": "CreateTextFileOutput",
"type": "object"
}
```
### Parameters
File ID
New content
Optional new name
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"mime_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mime Type"
},
"modified_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Modified Time"
},
"web_view_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web View Link"
}
},
"required": [
"success"
],
"title": "UpdateTextFileOutput",
"type": "object"
}
```
### Parameters
Folder name
Parent folder ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"web_view_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web View Link"
}
},
"required": [
"success"
],
"title": "CreateFolderOutput",
"type": "object"
}
```
### Parameters
Document name
Initial content (Default: ``)
Parent folder ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"web_view_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web View Link"
}
},
"required": [
"success"
],
"title": "CreateGoogleDocOutput",
"type": "object"
}
```
### Parameters
Document ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"content": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content"
},
"revision_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Revision Id"
}
},
"required": [
"success"
],
"title": "ReadGoogleDocOutput",
"type": "object"
}
```
### Parameters
Document ID
New content
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "UpdateGoogleDocOutput",
"type": "object"
}
```
### Parameters
Document ID
Content to append
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "AppendToGoogleDocOutput",
"type": "object"
}
```
### Parameters
Spreadsheet name
Initial data (2D array)
Parent folder ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"web_view_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web View Link"
}
},
"required": [
"success"
],
"title": "CreateGoogleSheetOutput",
"type": "object"
}
```
### Parameters
Spreadsheet ID
A1 notation (e.g. 'Sheet1!A1:D10') (Default: `Sheet1`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"spreadsheet_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Spreadsheet Id"
},
"range": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Range"
},
"values": {
"items": {
"items": {},
"type": "array"
},
"title": "Values",
"type": "array"
},
"row_count": {
"default": 0,
"title": "Row Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ReadGoogleSheetOutput",
"type": "object"
}
```
### Parameters
Spreadsheet ID
A1 notation
2D array of strings
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"spreadsheet_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Spreadsheet Id"
},
"updated_range": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated Range"
},
"updated_rows": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated Rows"
},
"updated_columns": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated Columns"
},
"updated_cells": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated Cells"
}
},
"required": [
"success"
],
"title": "UpdateGoogleSheetOutput",
"type": "object"
}
```
### Parameters
Spreadsheet ID
A1 range
RGB color {red, green, blue} (values 0-1)
LEFT / CENTER / RIGHT
TOP / MIDDLE / BOTTOM
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"spreadsheet_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Spreadsheet Id"
},
"range": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Range"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "FormatSheetCellsOutput",
"type": "object"
}
```
### Parameters
Spreadsheet ID
A1 range
Bold
Italic
Font size (pt)
Text RGB color {red, green, blue}
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"spreadsheet_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Spreadsheet Id"
},
"range": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Range"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "FormatSheetTextOutput",
"type": "object"
}
```
### Parameters
Presentation name
Parent folder ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"web_view_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web View Link"
}
},
"required": [
"success"
],
"title": "CreateGoogleSlidesOutput",
"type": "object"
}
```
### Parameters
Presentation ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"slide_count": {
"default": 0,
"title": "Slide Count",
"type": "integer"
},
"slides": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Slides",
"type": "array"
}
},
"required": [
"success"
],
"title": "ReadGoogleSlidesOutput",
"type": "object"
}
```
### Parameters
Presentation ID
BLANK / TITLE / TITLE_AND_BODY / etc. (Default: `BLANK`)
Insert position (0-based)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"presentation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Presentation Id"
},
"slide_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Slide Id"
},
"layout": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Layout"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "AddSlideOutput",
"type": "object"
}
```
### Parameters
Presentation ID
Slide object ID
Placeholder element ID
New text
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"presentation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Presentation Id"
},
"slide_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Slide Id"
},
"placeholder_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Placeholder Id"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "UpdateSlideContentOutput",
"type": "object"
}
```
## Related integrations
## Links
- [Google Drive](https://drive.google.com)
---
# Google Forms Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-forms
Create, update, and read Google Forms and their responses via the Google Forms API.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_forms/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google Forms** to any ModuleX agent or workflow. Create, update, and read Google Forms and their responses via the Google Forms REST API (`forms.googleapis.com/v1`).
**Categories**: Productivity & Collaboration · Forms & Surveys · **Auth**: OAuth2 · **Actions**: 6
## Authentication
### OAuth2 Authentication
Connect using Google OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Google OAuth App Client ID from the Google Cloud Console. | Yes | `xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com` |
| Client Secret | Google OAuth App Client Secret from the Google Cloud Console. | Yes | `GOCSPX-xxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Scopes**: `https://www.googleapis.com/auth/forms.body`, `https://www.googleapis.com/auth/forms.responses.readonly`
## Available Actions
### Parameters
The title of the form which is visible to responders.
The title of the document which is visible in Google Drive. Optional.
### Response
```json
{
"$defs": {
"FormInfo": {
"additionalProperties": false,
"description": "The ``info`` subobject embedded in a Google Form resource.",
"properties": {
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"documentTitle": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Documenttitle"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
}
},
"title": "FormInfo",
"type": "object"
},
"FormSummary": {
"additionalProperties": false,
"description": "Slim view of a Google Form resource returned by Get/Create.",
"properties": {
"formId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Formid"
},
"responderUri": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Responderuri"
},
"revisionId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Revisionid"
},
"info": {
"anyOf": [
{
"$ref": "#/$defs/FormInfo"
},
{
"type": "null"
}
],
"default": null
},
"settings": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Settings"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"title": "FormSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"form": {
"anyOf": [
{
"$ref": "#/$defs/FormSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateFormOutput",
"type": "object"
}
```
### Parameters
Identifier of the Google Form to update.
Title of the question.
Description of the question.
The 0-based index where the item is inserted in the form. Must be in the range [0..N), where N is the current number of items.
If true, the question is a paragraph (multi-line) question. If false, it is a short text question.
### Response
```json
{
"$defs": {
"FormInfo": {
"additionalProperties": false,
"description": "The ``info`` subobject embedded in a Google Form resource.",
"properties": {
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"documentTitle": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Documenttitle"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
}
},
"title": "FormInfo",
"type": "object"
},
"FormSummary": {
"additionalProperties": false,
"description": "Slim view of a Google Form resource returned by Get/Create.",
"properties": {
"formId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Formid"
},
"responderUri": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Responderuri"
},
"revisionId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Revisionid"
},
"info": {
"anyOf": [
{
"$ref": "#/$defs/FormInfo"
},
{
"type": "null"
}
],
"default": null
},
"settings": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Settings"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"title": "FormSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"formId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Formid"
},
"replies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Replies",
"type": "array"
},
"form": {
"anyOf": [
{
"$ref": "#/$defs/FormSummary"
},
{
"type": "null"
}
],
"default": null
},
"writeControl": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Writecontrol"
}
},
"required": [
"success"
],
"title": "CreateTextQuestionOutput",
"type": "object"
}
```
### Parameters
Identifier of the Google Form to retrieve.
### Response
```json
{
"$defs": {
"FormInfo": {
"additionalProperties": false,
"description": "The ``info`` subobject embedded in a Google Form resource.",
"properties": {
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"documentTitle": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Documenttitle"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
}
},
"title": "FormInfo",
"type": "object"
},
"FormSummary": {
"additionalProperties": false,
"description": "Slim view of a Google Form resource returned by Get/Create.",
"properties": {
"formId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Formid"
},
"responderUri": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Responderuri"
},
"revisionId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Revisionid"
},
"info": {
"anyOf": [
{
"$ref": "#/$defs/FormInfo"
},
{
"type": "null"
}
],
"default": null
},
"settings": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Settings"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"title": "FormSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"form": {
"anyOf": [
{
"$ref": "#/$defs/FormSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetFormOutput",
"type": "object"
}
```
### Parameters
Identifier of the Google Form the response belongs to.
The response ID within the form to retrieve.
### Response
```json
{
"$defs": {
"FormResponseSummary": {
"additionalProperties": false,
"description": "A single response to a Google Form.",
"properties": {
"responseId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Responseid"
},
"formId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Formid"
},
"createTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Createtime"
},
"lastSubmittedTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lastsubmittedtime"
},
"respondentEmail": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Respondentemail"
},
"answers": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Answers"
},
"totalScore": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Totalscore"
}
},
"title": "FormResponseSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"response": {
"anyOf": [
{
"$ref": "#/$defs/FormResponseSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetFormResponseOutput",
"type": "object"
}
```
### Parameters
Identifier of the Google Form whose responses are listed.
### Response
```json
{
"$defs": {
"FormResponseSummary": {
"additionalProperties": false,
"description": "A single response to a Google Form.",
"properties": {
"responseId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Responseid"
},
"formId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Formid"
},
"createTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Createtime"
},
"lastSubmittedTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lastsubmittedtime"
},
"respondentEmail": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Respondentemail"
},
"answers": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Answers"
},
"totalScore": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Totalscore"
}
},
"title": "FormResponseSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"responses": {
"items": {
"$ref": "#/$defs/FormResponseSummary"
},
"title": "Responses",
"type": "array"
},
"nextPageToken": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Nextpagetoken"
}
},
"required": [
"success"
],
"title": "ListFormResponsesOutput",
"type": "object"
}
```
### Parameters
Identifier of the Google Form to update.
The new title of the form which is visible to responders.
### Response
```json
{
"$defs": {
"FormInfo": {
"additionalProperties": false,
"description": "The ``info`` subobject embedded in a Google Form resource.",
"properties": {
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"documentTitle": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Documenttitle"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
}
},
"title": "FormInfo",
"type": "object"
},
"FormSummary": {
"additionalProperties": false,
"description": "Slim view of a Google Form resource returned by Get/Create.",
"properties": {
"formId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Formid"
},
"responderUri": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Responderuri"
},
"revisionId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Revisionid"
},
"info": {
"anyOf": [
{
"$ref": "#/$defs/FormInfo"
},
{
"type": "null"
}
],
"default": null
},
"settings": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Settings"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"title": "FormSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"formId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Formid"
},
"replies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Replies",
"type": "array"
},
"form": {
"anyOf": [
{
"$ref": "#/$defs/FormSummary"
},
{
"type": "null"
}
],
"default": null
},
"writeControl": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Writecontrol"
}
},
"required": [
"success"
],
"title": "UpdateFormTitleOutput",
"type": "object"
}
```
## Limits & Quotas
- The Google Forms API enforces per-project quotas administered through Google Cloud. Default quota is **300 read requests per minute per project** and **60 write requests per minute per project** (subject to change — see https://developers.google.com/forms/api/limits).
- Per-user quotas may apply for OAuth client credentials with many concurrent users.
- A `400 Bad Request` is returned when `index` for `create_text_question` is outside `[0..N)` where N is the current item count.
- **Error model:** non-2xx responses from the API raise `httpx.HTTPStatusError`, which the ModuleX runtime surfaces as a failed tool call with the original API error text included.
## Related integrations
## Links
- [Google Forms](https://forms.google.com)
---
# Google Maps Platform Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-maps-platform
Search for places and retrieve place details using the Google Places API (New)
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_maps_platform/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google Maps Platform** to any ModuleX agent or workflow. Search for places and retrieve place details using the Google Places API (New) (`places.googleapis.com`).
**Categories**: Developer Tools & Infrastructure · Geolocation · Maps & Places · **Auth**: Google Maps API Key · **Actions**: 2
## Authentication
### Google Maps API Key
Authenticate using your Google Cloud API key with Places API enabled
Go to https://console.cloud.google.com/apis/credentials
Create or select a project
Enable the Places API (New) for your project
Create an API key or use an existing one
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Google Maps API Key | Your Google Cloud API key with Places API (New) enabled | Yes | `AIzaSyXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX` |
## Available Actions
### Parameters
The text string on which to search, for example: 'restaurant', '123 Main Street', or 'best place to visit in San Francisco'
Restricts results to places matching the specified type from Table A (e.g. 'restaurant', 'cafe', 'hotel')
If true, include businesses that visit or deliver to customers directly but don't have a physical location
BCP-47 language code for results (e.g. 'en', 'fr', 'zh-CN')
Area to bias search results toward. JSON object with circle or rectangle specification
Area to restrict search results to. Results outside this area are not returned
Parameters for identifying available EV charging connectors and charging rates
Minimum average user rating (0.0 to 5.0 inclusive, in increments of 0.5)
If true, return only places that are currently open for business
Restrict to places at certain price levels. Valid values: PRICE_LEVEL_FREE, PRICE_LEVEL_INEXPENSIVE, PRICE_LEVEL_MODERATE, PRICE_LEVEL_EXPENSIVE, PRICE_LEVEL_VERY_EXPENSIVE
How results are ranked: RELEVANCE (by search relevance) or DISTANCE (by distance)
Two-character CLDR region code to format and bias results
When true and included_type is set, only return places matching the specified type
If true, return a reduced set of fields per place (id, name, type, status, rating, address, phone, website, hours, location)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"places": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Places",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchPlacesOutput",
"type": "object"
}
```
### Parameters
A textual identifier that uniquely identifies a place, returned from the search_places action
If true, return a reduced set of fields (id, name, type, status, rating, address, phone, website, hours, location)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetPlaceDetailsOutput",
"type": "object"
}
```
## Limits & Quotas
- **Text Search**: $32.00 per 1,000 requests (standard SKU pricing).
- **Place Details**: $17.00 per 1,000 requests (standard SKU pricing).
- **Default quota**: 6,000 QPM (queries per minute) per project; can be
increased via Google Cloud Console.
- **Error model**: non-2xx responses and timeouts are caught and returned as
`success=False` + `error` rather than raising.
## Related integrations
## Links
- [Google Maps Platform](https://developers.google.com/maps)
---
# Google Meet Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-meet
Schedule Google Meet video conferences via Google Calendar events.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_meet/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google Meet** to any ModuleX agent or workflow. Schedule Google Meet video conferences by creating Google Calendar events with an attached Meet link, via the Google Calendar REST API (`https://www.googleapis.com/calendar/v3`).
**Categories**: Communication · Productivity & Collaboration · **Auth**: OAuth2 · **Actions**: 2
## Authentication
### OAuth2 Authentication
Connect using Google OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Google Cloud OAuth 2.0 Client ID | Yes | `xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com` |
| Client Secret | Google Cloud OAuth 2.0 Client Secret | Yes | `GOCSPX-xxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Scopes**: `https://www.googleapis.com/auth/calendar`, `https://www.googleapis.com/auth/calendar.events`
## Available Actions
### Parameters
For all-day events use yyyy-mm-dd. For timed events use RFC3339 (yyyy-mm-ddThh:mm:ss+01:00). A time zone offset is required unless time_zone is set.
For all-day events use yyyy-mm-dd. For timed events use RFC3339 (yyyy-mm-ddThh:mm:ss+01:00). A time zone offset is required unless time_zone is set.
Calendar to create the event on. Defaults to 'primary' (the authenticated user's primary calendar). (Default: `primary`)
Title of the event (e.g. 'Weekly sync').
Physical or virtual location of the event.
Long-form description of the event.
List of attendee email addresses to invite.
RRULE strings describing recurrence (e.g. 'RRULE:FREQ=DAILY;INTERVAL=2').
IANA time zone name used for start/end (e.g. 'America/Los_Angeles'). Defaults to the calendar's time zone.
Whether to notify attendees: 'all', 'externalOnly', or 'none'.
Whether to send notifications about the event update.
Color ID for the event. Use list_color_id_options to discover valid values.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"event_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Event Id"
},
"html_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Html Link"
},
"hangout_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hangout Link"
},
"meet_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Meet Link"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"start": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Start"
},
"end": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "End"
},
"attendees": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Attendees",
"type": "array"
},
"conference_data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Conference Data"
},
"event": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Event"
}
},
"required": [
"success"
],
"title": "ScheduleMeetingOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"ColorIdOption": {
"additionalProperties": false,
"description": "One color option exposed by the Google Calendar /colors endpoint.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"background": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Background"
},
"foreground": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Foreground"
}
},
"title": "ColorIdOption",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"options": {
"items": {
"$ref": "#/$defs/ColorIdOption"
},
"title": "Options",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListColorIdOptionsOutput",
"type": "object"
}
```
## Limits & Quotas
- Google Calendar API default quota: **1,000,000 queries/day** per project, with
per-user limits of **600 queries/minute**. See the
[Google Calendar API quotas page](https://developers.google.com/calendar/api/guides/quota)
for details.
- `schedule_meeting` sends `conferenceDataVersion=1` so Google provisions a Meet
link in the same call (counts as a single event-insert quota unit).
- **Error model**: non-2xx responses and timeouts are caught and returned as
`success=False` + `error` rather than raising. Plan for retries on the agent
side based on the error string. 401/403 typically means the OAuth token has
expired or lacks the calendar scope.
## Related integrations
## Links
- [Google Meet](https://meet.google.com)
---
# Google Merchant Center Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-merchant-center
Manage product listings in Google Merchant Center via the Shopping Content API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_merchant_center/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google Merchant Center** to any ModuleX agent or workflow. Manage product listings in Google Merchant Center via the Shopping Content API (`shoppingcontent.googleapis.com/content/v2.1`).
**Categories**: E-Commerce · Marketing · Google · **Auth**: OAuth2 · **Actions**: 2
## Authentication
### OAuth2 Authentication
Connect using Google OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Google OAuth App Client ID | Yes | `-` |
| Client Secret | Google OAuth App Client Secret | Yes | `-` |
| Merchant ID | Your Google Merchant Center account ID (numeric) | Yes | `123456789` |
#### OAuth Configuration
- **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Scopes**: `https://www.googleapis.com/auth/content`
## Available Actions
### Parameters
A unique identifier for the item
The two-letter ISO 639-1 language code for the item (e.g. 'en', 'fr', 'de')
The CLDR territory code for the item's country of sale (e.g. 'US', 'GB', 'DE')
The item's channel: 'local' or 'online'
Your product's name (max 150 characters)
Your product's description (max 5000 characters)
Additional product attributes as a JSON object (e.g. 'link', 'imageLink', 'price', 'availability')
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateProductOutput",
"type": "object"
}
```
### Parameters
The ID of the product to update (e.g. 'online:en:US:offer123')
Product attributes to update as a JSON object with attribute names as keys
List of product attribute names to update. Attributes in this list without a value in updated_values will be deleted
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "UpdateProductOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limits**: Google Shopping Content API has per-project and per-user quotas managed via the Google Cloud Console. Default is approximately 7,000 requests per 100 seconds per project.
- **Error model**: Non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Google Merchant Center](https://merchants.google.com)
---
# Google My Business Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-my-business
Manage Google Business Profile posts, reviews, and replies
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_my_business/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google My Business** to any ModuleX agent or workflow. Manage Google Business Profile posts, reviews, and replies via the Google My Business API (`mybusiness.googleapis.com/v4`).
**Categories**: Marketing & Advertising · Marketing · Local Business · Reviews · **Auth**: OAuth2 · **Actions**: 6
## Authentication
### OAuth2 Authentication
Connect using Google OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Google OAuth App Client ID | Yes | `123456789-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com` |
| Client Secret | Google OAuth App Client Secret | Yes | `GOCSPX-xxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Scopes**: `https://www.googleapis.com/auth/business.manage`
## Available Actions
### Parameters
Account name/ID for the Google Business Profile account
Location name/ID whose local posts will be created
Topic type of the local post: STANDARD, EVENT, OFFER, or ALERT
Language of the local post (e.g. en-US)
Description/body of the local post
Action performed when user clicks through the post. Object with actionType and url fields
Event information. Required for topic types EVENT and OFFER. Object with title, schedule (startDate, startTime, endDate, endTime)
Media associated with the post. Array of objects with sourceUrl (publicly accessible URL) fields
Format of the media items: PHOTO or VIDEO
Type of alert for ALERT topic type: ALERT_TYPE_UNSPECIFIED or COVID_19
Additional data for offer posts (only for OFFER topic type). Object with couponCode, redeemOnlineUrl, termsConditions
### Response
```json
{
"$defs": {
"LocalPost": {
"additionalProperties": false,
"description": "A Google My Business local post.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"topic_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Topic Type"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"create_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Create Time"
},
"update_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Update Time"
},
"search_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Search Url"
},
"event": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Event"
},
"offer": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Offer"
},
"call_to_action": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Call To Action"
}
},
"title": "LocalPost",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"post": {
"anyOf": [
{
"$ref": "#/$defs/LocalPost"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreatePostOutput",
"type": "object"
}
```
### Parameters
Account name/ID for the Google Business Profile account
Location name/ID of the review
Review name/ID to reply to
Body of the reply as plain text (max 4096 bytes)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"comment": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Comment"
},
"update_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Update Time"
}
},
"required": [
"success"
],
"title": "CreateUpdateReplyToReviewOutput",
"type": "object"
}
```
### Parameters
Account name/ID for the Google Business Profile account
List of location name/ID strings to get reviews from
Number of reviews to return per location (max 50) (Default: `50`)
How to order reviews: 'createTime desc', 'createTime asc', 'updateTime desc', or 'updateTime asc'
If true, only return reviews that have textual content (Default: `false`)
### Response
```json
{
"$defs": {
"LocationReview": {
"additionalProperties": false,
"description": "A review associated with a location in a batch response.",
"properties": {
"location_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location Name"
},
"reviews": {
"items": {
"$ref": "#/$defs/Review"
},
"title": "Reviews",
"type": "array"
}
},
"title": "LocationReview",
"type": "object"
},
"Review": {
"additionalProperties": false,
"description": "A Google My Business review.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"review_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Review Id"
},
"reviewer_display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Reviewer Display Name"
},
"star_rating": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Star Rating"
},
"comment": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Comment"
},
"create_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Create Time"
},
"update_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Update Time"
},
"review_reply": {
"anyOf": [
{
"$ref": "#/$defs/ReviewReply"
},
{
"type": "null"
}
],
"default": null
}
},
"title": "Review",
"type": "object"
},
"ReviewReply": {
"additionalProperties": false,
"description": "A reply to a review.",
"properties": {
"comment": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Comment"
},
"update_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Update Time"
}
},
"title": "ReviewReply",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"location_reviews": {
"items": {
"$ref": "#/$defs/LocationReview"
},
"title": "Location Reviews",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetReviewsMultipleLocationsOutput",
"type": "object"
}
```
### Parameters
Account name/ID for the Google Business Profile account
Location name/ID of the review
Review name/ID to retrieve
### Response
```json
{
"$defs": {
"Review": {
"additionalProperties": false,
"description": "A Google My Business review.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"review_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Review Id"
},
"reviewer_display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Reviewer Display Name"
},
"star_rating": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Star Rating"
},
"comment": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Comment"
},
"create_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Create Time"
},
"update_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Update Time"
},
"review_reply": {
"anyOf": [
{
"$ref": "#/$defs/ReviewReply"
},
{
"type": "null"
}
],
"default": null
}
},
"title": "Review",
"type": "object"
},
"ReviewReply": {
"additionalProperties": false,
"description": "A reply to a review.",
"properties": {
"comment": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Comment"
},
"update_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Update Time"
}
},
"title": "ReviewReply",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"review": {
"anyOf": [
{
"$ref": "#/$defs/Review"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetSpecificReviewOutput",
"type": "object"
}
```
### Parameters
Account name/ID for the Google Business Profile account
Location name/ID whose reviews will be listed
### Response
```json
{
"$defs": {
"Review": {
"additionalProperties": false,
"description": "A Google My Business review.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"review_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Review Id"
},
"reviewer_display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Reviewer Display Name"
},
"star_rating": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Star Rating"
},
"comment": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Comment"
},
"create_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Create Time"
},
"update_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Update Time"
},
"review_reply": {
"anyOf": [
{
"$ref": "#/$defs/ReviewReply"
},
{
"type": "null"
}
],
"default": null
}
},
"title": "Review",
"type": "object"
},
"ReviewReply": {
"additionalProperties": false,
"description": "A reply to a review.",
"properties": {
"comment": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Comment"
},
"update_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Update Time"
}
},
"title": "ReviewReply",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"reviews": {
"items": {
"$ref": "#/$defs/Review"
},
"title": "Reviews",
"type": "array"
},
"next_page_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page Token"
}
},
"required": [
"success"
],
"title": "ListAllReviewsOutput",
"type": "object"
}
```
### Parameters
Account name/ID for the Google Business Profile account
Location name/ID whose local posts will be listed
Max number of posts to retrieve (each request retrieves up to 100, maximum 1000) (Default: `100`)
### Response
```json
{
"$defs": {
"LocalPost": {
"additionalProperties": false,
"description": "A Google My Business local post.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"topic_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Topic Type"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"create_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Create Time"
},
"update_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Update Time"
},
"search_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Search Url"
},
"event": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Event"
},
"offer": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Offer"
},
"call_to_action": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Call To Action"
}
},
"title": "LocalPost",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"posts": {
"items": {
"$ref": "#/$defs/LocalPost"
},
"title": "Posts",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListPostsOutput",
"type": "object"
}
```
## Limits & Quotas
- Google My Business API is subject to Google Cloud project quotas (typically 60 requests/minute per project by default).
- Some endpoints may return 429 status if quota is exceeded.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Google My Business](https://business.google.com)
---
# Google Search Console Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-search-console
Access Google Search Console data for search analytics and URL indexing
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_search_console/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google Search Console** to any ModuleX agent or workflow. Access Google Search Console search analytics and URL indexing via the Search Console API (`searchconsole.googleapis.com`) and the Indexing API (`indexing.googleapis.com`).
**Categories**: Marketing & Advertising · SEO · Marketing · Developer Tools & Infrastructure · **Auth**: OAuth2 · **Actions**: 2
## Authentication
### OAuth2 Authentication
Connect using Google OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Google OAuth App Client ID | Yes | `-` |
| Client Secret | Google OAuth App Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Scopes**: `https://www.googleapis.com/auth/webmasters.readonly`, `https://www.googleapis.com/auth/indexing`
## Available Actions
### Parameters
The site URL as registered in Search Console (e.g. 'sc-domain:example.com' or 'https://example.com/')
Start date in YYYY-MM-DD format
End date in YYYY-MM-DD format
Dimensions to group results by. Allowed values: country, device, page, query, searchAppearance, date
Type of search. Allowed values: web, image, video, news, googleNews, discover (Default: `web`)
Aggregation type. Allowed values: auto, byPage
Maximum number of rows to return (Default: `10`)
Start row for pagination (zero-based)
Filter results to a specific subdomain when using a domain property (e.g. 'https://subdomain.example.com')
Dimension to filter by when subdomain_filter is used. Allowed values: country, device, page, query (Default: `page`)
Filter operator. Allowed values: contains, equals, notContains, notEquals, includingRegex, excludingRegex (Default: `contains`)
Custom dimension filter groups following the Search Console API structure (JSON object)
Data state to use. Allowed values: all, final (Default: `final`)
### Response
```json
{
"$defs": {
"SearchAnalyticsRow": {
"additionalProperties": false,
"description": "A single row from the Search Analytics response.",
"properties": {
"keys": {
"items": {
"type": "string"
},
"title": "Keys",
"type": "array"
},
"clicks": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Clicks"
},
"impressions": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Impressions"
},
"ctr": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Ctr"
},
"position": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Position"
}
},
"title": "SearchAnalyticsRow",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"rows": {
"items": {
"$ref": "#/$defs/SearchAnalyticsRow"
},
"title": "Rows",
"type": "array"
},
"response_aggregation_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Response Aggregation Type"
}
},
"required": [
"success"
],
"title": "RetrieveSitePerformanceDataOutput",
"type": "object"
}
```
### Parameters
The URL to submit for indexing (must be a canonical URL verified in Google Search Console)
Type of notification. Allowed values: URL_UPDATED (content updated), URL_DELETED (page removed) (Default: `URL_UPDATED`)
### Response
```json
{
"$defs": {
"UrlNotificationMetadata": {
"additionalProperties": false,
"description": "Metadata returned after submitting a URL for indexing.",
"properties": {
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"latest_update": {
"anyOf": [
{
"additionalProperties": {
"type": "string"
},
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Latest Update"
},
"latest_remove": {
"anyOf": [
{
"additionalProperties": {
"type": "string"
},
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Latest Remove"
}
},
"title": "UrlNotificationMetadata",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"url_notification_metadata": {
"anyOf": [
{
"$ref": "#/$defs/UrlNotificationMetadata"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "SubmitUrlForIndexingOutput",
"type": "object"
}
```
## Limits & Quotas
- **Search Analytics API**: 1,200 queries per minute per project (default quota).
- **Indexing API**: 200 publish requests per day per site property (standard quota).
- **Error model**: non-2xx responses are caught and returned as `success=False` + `error`
rather than raising.
## Related integrations
## Links
- [Google Search Console](https://search.google.com/search-console)
---
# Google Sheets Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-sheets
Read, write, and manage Google Sheets spreadsheets and worksheets.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_sheets/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google Sheets** to any ModuleX agent or workflow. Read, write, and manage Google Sheets spreadsheets and worksheets via the Google Sheets API v4 (`https://sheets.googleapis.com/v4`).
**Categories**: Productivity & Collaboration · Data & Analytics · **Auth**: OAuth2 · **Actions**: 13
## Authentication
### OAuth2 Authentication
Connect using Google OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Google OAuth Client ID | Yes | `xxxxxxxxxxxx.apps.googleusercontent.com` |
| Client Secret | Google OAuth Client Secret | Yes | `GOCSPX-xxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Scopes**: `https://www.googleapis.com/auth/spreadsheets`, `https://www.googleapis.com/auth/drive.file`
## Available Actions
### Parameters
The title of the new spreadsheet.
Name for the first worksheet. Default: 'Sheet1'.
Column headers to add as row 1. Each item is a string. Example: ["Name", "Email", "Score"].
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"spreadsheet_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Spreadsheet Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"worksheet_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Worksheet Name"
}
},
"required": [
"success"
],
"title": "NewSpreadsheetOutput",
"type": "object"
}
```
### Parameters
The spreadsheet ID from the Google Sheets URL.
### Response
```json
{
"$defs": {
"WorksheetInfo": {
"additionalProperties": false,
"description": "A worksheet summary plus its row-1 headers, used by get_spreadsheet_info.",
"properties": {
"sheet_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sheet Name"
},
"sheet_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Sheet Id"
},
"row_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Row Count"
},
"headers": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Headers"
}
},
"title": "WorksheetInfo",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"spreadsheet_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Spreadsheet Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"worksheets": {
"anyOf": [
{
"items": {
"$ref": "#/$defs/WorksheetInfo"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Worksheets"
}
},
"required": [
"success"
],
"title": "GetSpreadsheetInfoOutput",
"type": "object"
}
```
### Parameters
The spreadsheet ID from the Google Sheets URL.
### Response
```json
{
"$defs": {
"WorksheetSummary": {
"additionalProperties": false,
"description": "A worksheet (tab) summary as returned by list/info actions.",
"properties": {
"sheet_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Sheet Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"index": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Index"
},
"sheet_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sheet Type"
},
"row_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Row Count"
},
"column_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Column Count"
}
},
"title": "WorksheetSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"worksheets": {
"anyOf": [
{
"items": {
"$ref": "#/$defs/WorksheetSummary"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Worksheets"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
}
},
"required": [
"success"
],
"title": "ListWorksheetsOutput",
"type": "object"
}
```
### Parameters
The spreadsheet ID from the Google Sheets URL.
The name of the new worksheet (tab).
Column headers to add as row 1. Each item is a string. Example: ["Name", "Email", "Score"].
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"sheet_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Sheet Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"index": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Index"
}
},
"required": [
"success"
],
"title": "AddWorksheetOutput",
"type": "object"
}
```
### Parameters
The spreadsheet ID from the Google Sheets URL.
The numeric worksheet (sheet) ID to delete. Use get_spreadsheet_info to discover sheet IDs.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"spreadsheet_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Spreadsheet Id"
},
"deleted_sheet_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted Sheet Id"
}
},
"required": [
"success"
],
"title": "DeleteWorksheetOutput",
"type": "object"
}
```
### Parameters
The spreadsheet ID from the Google Sheets URL.
The worksheet (tab) name.
Optional A1 notation range within the sheet (e.g. 'A1:D10', 'A:F'). Omit to read all data.
Whether row 1 contains column headers. If true, returns rows as objects with header keys. (Default: `true`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"headers": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Headers"
},
"rows": {
"anyOf": [
{
"items": {},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Rows"
},
"row_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Row Count"
}
},
"required": [
"success"
],
"title": "ReadRowsOutput",
"type": "object"
}
```
### Parameters
The spreadsheet ID from the Google Sheets URL.
The worksheet (tab) name.
A1 notation range within the sheet (e.g. 'A1:E5'). Omit to read the entire sheet.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"range": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Range"
},
"values": {
"anyOf": [
{
"items": {
"items": {},
"type": "array"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Values"
},
"row_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Row Count"
}
},
"required": [
"success"
],
"title": "GetValuesInRangeOutput",
"type": "object"
}
```
### Parameters
The spreadsheet ID from the Google Sheets URL.
The worksheet (tab) name.
Column header name (e.g. 'Name') or column letter (e.g. 'A', 'B').
The value to search for.
How to match. Valid values: 'exact' (case-insensitive exact match), 'contains' (substring), 'starts_with'. (Default: `contains`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"matches": {
"anyOf": [
{
"items": {
"additionalProperties": true,
"type": "object"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Matches"
},
"match_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Match Count"
}
},
"required": [
"success"
],
"title": "FindRowsOutput",
"type": "object"
}
```
### Parameters
The spreadsheet ID from the Google Sheets URL.
The worksheet (tab) name.
Array of rows to append. Each row is either an array of positional cell values or an object whose keys match the worksheet's column headers.
Whether row 1 contains column headers. Required when passing rows as objects. (Default: `true`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"rows_added": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Rows Added"
},
"updated_range": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated Range"
},
"updated_rows": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated Rows"
},
"updated_columns": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated Columns"
},
"updated_cells": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated Cells"
}
},
"required": [
"success"
],
"title": "AddRowsOutput",
"type": "object"
}
```
### Parameters
The spreadsheet ID from the Google Sheets URL.
The worksheet (tab) name.
1-indexed row number to update.
Array of cell values for the row, in column order. Numbers, strings, and booleans are all accepted.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"updated_range": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated Range"
},
"updated_rows": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated Rows"
},
"updated_columns": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated Columns"
},
"updated_cells": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated Cells"
}
},
"required": [
"success"
],
"title": "UpdateRowOutput",
"type": "object"
}
```
### Parameters
The spreadsheet ID from the Google Sheets URL.
The worksheet (tab) name.
A1 notation for the cell (e.g. 'B5').
The new cell value.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"updated_range": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated Range"
},
"updated_cells": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated Cells"
}
},
"required": [
"success"
],
"title": "UpdateCellOutput",
"type": "object"
}
```
### Parameters
The spreadsheet ID from the Google Sheets URL.
The worksheet (tab) name.
1-indexed row number of the first row to clear (inclusive).
1-indexed row number of the last row to clear (inclusive). Omit to clear only the start row.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"spreadsheet_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Spreadsheet Id"
},
"cleared_range": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cleared Range"
}
},
"required": [
"success"
],
"title": "ClearRowsOutput",
"type": "object"
}
```
### Parameters
The spreadsheet ID from the Google Sheets URL.
The numeric worksheet (sheet) ID. Use get_spreadsheet_info to discover sheet IDs.
1-indexed row number of the first row to delete (inclusive).
1-indexed row number of the last row to delete (inclusive). Omit to delete only the start row.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"spreadsheet_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Spreadsheet Id"
},
"deleted_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted Count"
}
},
"required": [
"success"
],
"title": "DeleteRowsOutput",
"type": "object"
}
```
## Limits & Quotas
- Google Sheets API default quota: 300 read requests / minute / project and 300
write requests / minute / project (with a 60 / minute / user cap for both).
- Cell-value writes use `valueInputOption=USER_ENTERED`, so values are parsed as
if a user typed them in the UI (numbers/dates/booleans get coerced).
- `add_rows` uses `insertDataOption=INSERT_ROWS`, so it never overwrites
existing data — new rows are inserted after the last row containing data.
- Non-2xx responses are caught and returned as `success=False` + `error` with
the API `error.message` (when present).
- Timeouts surface as `success=False` with `error="Request timed out."`.
## Related integrations
## Links
- [Google Sheets](https://www.google.com/sheets/about/)
---
# Google Slides Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-slides
Create and edit Google Slides presentations — manage slides, shapes, images, tables, and text via the Google Slides REST API.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_slides/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google Slides** to any ModuleX agent or workflow. Create and edit Google Slides presentations from agents — manage slides, shapes, images, tables, and text via the Google Slides REST API (`slides.googleapis.com/v1`).
**Categories**: Productivity & Collaboration · Document Management · **Auth**: OAuth2 · **Actions**: 15
## Authentication
### OAuth2 Authentication
Connect using Google OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Google Cloud OAuth 2.0 Client ID | Yes | `1234567890-abcdefghijklmnop.apps.googleusercontent.com` |
| Client Secret | Google Cloud OAuth 2.0 Client Secret | Yes | `GOCSPX-xxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Scopes**: `https://www.googleapis.com/auth/presentations`
## Available Actions
### Parameters
ID of the target Google Slides presentation.
Object ID of the slide (page) on which to place the image.
Publicly accessible URL of the image to insert; must be reachable by Google's servers.
Height of the image in points (1 pt = 1/72 inch).
Width of the image in points (1 pt = 1/72 inch).
Horizontal scale factor for the image. (Default: `1`)
Vertical scale factor for the image. (Default: `1`)
Horizontal translation (offset) of the image in points. (Default: `0`)
Vertical translation (offset) of the image in points. (Default: `0`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"presentation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Presentation Id"
},
"image_object_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Image Object Id"
},
"replies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Replies",
"type": "array"
},
"write_control": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Write Control"
}
},
"required": [
"success"
],
"title": "CreateImageOutput",
"type": "object"
}
```
### Parameters
ID of the target Google Slides presentation.
Object ID of the slide on which to place the shape.
Shape type. Common values: 'TEXT_BOX', 'RECTANGLE', 'ELLIPSE', 'ROUND_RECTANGLE', 'ARROW_EAST', 'RIGHT_ARROW', 'STAR_5', 'CLOUD'. See Google Slides API Type enum for the full list.
Height of the shape in points (1 pt = 1/72 inch).
Width of the shape in points (1 pt = 1/72 inch).
Horizontal scale factor for the shape. (Default: `1`)
Vertical scale factor for the shape. (Default: `1`)
Horizontal translation (offset) of the shape in points. (Default: `0`)
Vertical translation (offset) of the shape in points. (Default: `0`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"presentation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Presentation Id"
},
"shape_object_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Shape Object Id"
},
"replies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Replies",
"type": "array"
},
"write_control": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Write Control"
}
},
"required": [
"success"
],
"title": "CreatePageElementOutput",
"type": "object"
}
```
### Parameters
Title of the new presentation.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"presentation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Presentation Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"revision_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Revision Id"
},
"raw": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Raw"
}
},
"required": [
"success"
],
"title": "CreatePresentationOutput",
"type": "object"
}
```
### Parameters
ID of the target Google Slides presentation.
Object ID of the slide layout to apply (from presentation.layouts[*].objectId).
Optional 0-based index where the slide is inserted. Omit to append at the end.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"presentation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Presentation Id"
},
"slide_object_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Slide Object Id"
},
"replies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Replies",
"type": "array"
},
"write_control": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Write Control"
}
},
"required": [
"success"
],
"title": "CreateSlideOutput",
"type": "object"
}
```
### Parameters
ID of the target Google Slides presentation.
Object ID of the slide on which to place the table.
Number of rows in the table.
Number of columns in the table.
Height of the table in points (1 pt = 1/72 inch).
Width of the table in points (1 pt = 1/72 inch).
Optional horizontal translation (offset) of the table in points.
Optional vertical translation (offset) of the table in points.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"presentation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Presentation Id"
},
"table_object_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Table Object Id"
},
"replies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Replies",
"type": "array"
},
"write_control": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Write Control"
}
},
"required": [
"success"
],
"title": "CreateTableOutput",
"type": "object"
}
```
### Parameters
ID of the target Google Slides presentation.
Object ID of the page element to delete.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"presentation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Presentation Id"
},
"deleted_object_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted Object Id"
},
"replies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Replies",
"type": "array"
},
"write_control": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Write Control"
}
},
"required": [
"success"
],
"title": "DeletePageElementOutput",
"type": "object"
}
```
### Parameters
ID of the target Google Slides presentation.
Object ID of the slide to delete.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"presentation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Presentation Id"
},
"deleted_slide_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted Slide Id"
},
"replies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Replies",
"type": "array"
},
"write_control": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Write Control"
}
},
"required": [
"success"
],
"title": "DeleteSlideOutput",
"type": "object"
}
```
### Parameters
ID of the target Google Slides presentation.
Object ID of the table to modify.
0-based index of the column inside the table to delete.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"presentation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Presentation Id"
},
"replies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Replies",
"type": "array"
},
"write_control": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Write Control"
}
},
"required": [
"success"
],
"title": "DeleteTableColumnOutput",
"type": "object"
}
```
### Parameters
ID of the target Google Slides presentation.
Object ID of the table to modify.
0-based index of the row inside the table to delete.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"presentation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Presentation Id"
},
"replies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Replies",
"type": "array"
},
"write_control": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Write Control"
}
},
"required": [
"success"
],
"title": "DeleteTableRowOutput",
"type": "object"
}
```
### Parameters
ID of the Google Slides presentation to retrieve.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"presentation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Presentation Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"locale": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Locale"
},
"revision_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Revision Id"
},
"page_size": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Page Size"
},
"slides": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Slides",
"type": "array"
},
"layouts": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Layouts",
"type": "array"
},
"masters": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Masters",
"type": "array"
},
"notes_master": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Notes Master"
},
"raw": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Raw"
}
},
"required": [
"success"
],
"title": "FindPresentationOutput",
"type": "object"
}
```
### Parameters
ID of the target Google Slides presentation.
Object ID of the table to modify.
Optional 0-based column index of the reference cell.
Whether the new columns are inserted to the right of the reference cell.
Number of columns to insert (max 20 per request). (Default: `1`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"presentation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Presentation Id"
},
"replies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Replies",
"type": "array"
},
"write_control": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Write Control"
}
},
"required": [
"success"
],
"title": "InsertTableColumnsOutput",
"type": "object"
}
```
### Parameters
ID of the target Google Slides presentation.
Object ID of the table to modify.
Optional 0-based row index of the reference cell.
Whether the new rows are inserted below the reference cell.
Number of rows to insert (max 20 per request). (Default: `1`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"presentation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Presentation Id"
},
"replies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Replies",
"type": "array"
},
"write_control": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Write Control"
}
},
"required": [
"success"
],
"title": "InsertTableRowsOutput",
"type": "object"
}
```
### Parameters
ID of the target Google Slides presentation.
Object ID of the target shape (must contain a text frame, e.g. a TEXT_BOX).
Text content to insert into the shape.
Optional 0-based character index at which to insert the text. Omit to append at the end.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"presentation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Presentation Id"
},
"replies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Replies",
"type": "array"
},
"write_control": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Write Control"
}
},
"required": [
"success"
],
"title": "InsertTextOutput",
"type": "object"
}
```
### Parameters
ID of the target Google Slides presentation.
Object ID of the target table.
Text content to insert into the table cell.
Optional 0-based row index of the target cell.
Optional 0-based column index of the target cell.
Optional 0-based character index within the cell at which to insert the text. Omit to append at the end.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"presentation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Presentation Id"
},
"replies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Replies",
"type": "array"
},
"write_control": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Write Control"
}
},
"required": [
"success"
],
"title": "InsertTextIntoTableOutput",
"type": "object"
}
```
### Parameters
ID of the target Google Slides presentation.
Text snippet to search for.
Replacement text inserted for every match found.
Optional list of slide page object IDs (strings). When supplied, only page elements on these pages are searched.
Whether the text match is case-sensitive.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"presentation_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Presentation Id"
},
"total_occurrences_changed": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Occurrences Changed"
},
"replies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Replies",
"type": "array"
},
"write_control": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Write Control"
}
},
"required": [
"success"
],
"title": "ReplaceAllTextOutput",
"type": "object"
}
```
## Limits & Quotas
- **Per-project quotas**: Google Slides API defaults to a few hundred read or write requests per 100 seconds per project; per-user limits also apply (see the [Slides API quotas page](https://developers.google.com/workspace/slides/api/limits)). Quotas are managed in the Google Cloud Console (APIs & Services -> Quotas).
- **batchUpdate body**: Slides `batchUpdate` requests should stay under ~10 MB; for very large updates, batch the work into multiple calls.
- **Insert table rows/columns**: capped at 20 per single request, per Google's documented `InsertTableRowsRequest` / `InsertTableColumnsRequest` limits.
- **Error model**: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising. Plan for retries on the agent side based on the error string. OAuth tokens that have expired surface as HTTP 401 in the `error` field.
## Related integrations
## Links
- [Google Slides](https://slides.google.com)
---
# Google Tag Manager Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-tag-manager
Manage tags, variables, and workspaces in Google Tag Manager containers
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_tag_manager/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google Tag Manager** to any ModuleX agent or workflow. Manage tags, variables, and workspaces in Google Tag Manager containers via the Tag Manager API v2 (`www.googleapis.com/tagmanager/v2`).
**Categories**: Analytics & Data · Analytics · Marketing · **Auth**: OAuth2 · **Actions**: 6
## Authentication
### OAuth2 Authentication
Connect using Google OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Google OAuth App Client ID | Yes | `-` |
| Client Secret | Google OAuth App Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Scopes**: `https://www.googleapis.com/auth/tagmanager.edit.containers`, `https://www.googleapis.com/auth/tagmanager.readonly`
## Available Actions
### Parameters
The Google Tag Manager account ID
The container ID
The workspace ID
The name of the tag
The type of the tag (see Tag Dictionary Reference)
JSON string representing the list of parameters for the tag
Whether the tag should only fire in the live environment
Any notes or comments about the tag
JSON string representing consent settings for the tag
JSON string representing monitoring metadata for the tag
### Response
```json
{
"$defs": {
"TagResource": {
"additionalProperties": false,
"description": "A Google Tag Manager tag resource.",
"properties": {
"tag_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Tag Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"live_only": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Live Only"
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Notes"
},
"parameter": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Parameter",
"type": "array"
},
"fingerprint": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Fingerprint"
},
"tag_manager_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Tag Manager Url"
},
"path": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path"
},
"account_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Account Id"
},
"container_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Container Id"
},
"workspace_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Workspace Id"
}
},
"title": "TagResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"tag": {
"anyOf": [
{
"$ref": "#/$defs/TagResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateTagOutput",
"type": "object"
}
```
### Parameters
The Google Tag Manager account ID
The container ID
The workspace ID
The tag ID
### Response
```json
{
"$defs": {
"TagResource": {
"additionalProperties": false,
"description": "A Google Tag Manager tag resource.",
"properties": {
"tag_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Tag Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"live_only": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Live Only"
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Notes"
},
"parameter": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Parameter",
"type": "array"
},
"fingerprint": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Fingerprint"
},
"tag_manager_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Tag Manager Url"
},
"path": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path"
},
"account_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Account Id"
},
"container_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Container Id"
},
"workspace_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Workspace Id"
}
},
"title": "TagResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"tag": {
"anyOf": [
{
"$ref": "#/$defs/TagResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetTagOutput",
"type": "object"
}
```
### Parameters
The Google Tag Manager account ID
The container ID
The workspace ID
### Response
```json
{
"$defs": {
"TagResource": {
"additionalProperties": false,
"description": "A Google Tag Manager tag resource.",
"properties": {
"tag_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Tag Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"live_only": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Live Only"
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Notes"
},
"parameter": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Parameter",
"type": "array"
},
"fingerprint": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Fingerprint"
},
"tag_manager_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Tag Manager Url"
},
"path": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path"
},
"account_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Account Id"
},
"container_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Container Id"
},
"workspace_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Workspace Id"
}
},
"title": "TagResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"tags": {
"items": {
"$ref": "#/$defs/TagResource"
},
"title": "Tags",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetTagsOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"AccountItem": {
"additionalProperties": false,
"description": "A Google Tag Manager account.",
"properties": {
"account_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Account Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"share_data": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Share Data"
},
"fingerprint": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Fingerprint"
},
"path": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path"
},
"tag_manager_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Tag Manager Url"
}
},
"title": "AccountItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"accounts": {
"items": {
"$ref": "#/$defs/AccountItem"
},
"title": "Accounts",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListAccountIdOptionsOutput",
"type": "object"
}
```
### Parameters
The Google Tag Manager account ID
The container ID
The workspace ID
The tag ID
The type of the tag (see Tag Dictionary Reference)
JSON string representing the list of parameters for the tag
The name of the tag
Whether the tag should only fire in the live environment
Any notes or comments about the tag
JSON string representing consent settings for the tag
JSON string representing monitoring metadata for the tag
### Response
```json
{
"$defs": {
"TagResource": {
"additionalProperties": false,
"description": "A Google Tag Manager tag resource.",
"properties": {
"tag_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Tag Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"live_only": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Live Only"
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Notes"
},
"parameter": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Parameter",
"type": "array"
},
"fingerprint": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Fingerprint"
},
"tag_manager_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Tag Manager Url"
},
"path": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path"
},
"account_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Account Id"
},
"container_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Container Id"
},
"workspace_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Workspace Id"
}
},
"title": "TagResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"tag": {
"anyOf": [
{
"$ref": "#/$defs/TagResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UpdateTagOutput",
"type": "object"
}
```
### Parameters
The Google Tag Manager account ID
The container ID
The workspace ID
The variable ID
The name of the variable
The type of the variable (e.g. 'jsm')
JSON string representing the list of parameters for the variable
JSON string representing the formatValue object for the variable
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "UpdateVariableOutput",
"type": "object"
}
```
## Limits & Quotas
- Google Tag Manager API uses per-project quotas managed via the Google Cloud Console.
- Default quota: 10,000 requests per day per project (varies by endpoint).
- Rate limit: approximately 5 requests per second per user.
- Error model: non-2xx responses raise `httpx.HTTPStatusError` (Pattern A).
## Related integrations
## Links
- [Google Tag Manager](https://tagmanager.google.com)
---
# Google Tasks Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-tasks
Manage tasks and task lists using the Google Tasks API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_tasks/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google Tasks** to any ModuleX agent or workflow. Manage tasks and task lists using the Google Tasks REST API (`tasks.googleapis.com/tasks/v1`).
**Categories**: Productivity & Collaboration · Task Management · **Auth**: OAuth2 · **Actions**: 8
## Authentication
### OAuth2 Authentication
Connect using Google OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Google OAuth App Client ID | Yes | `xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com` |
| Client Secret | Google OAuth App Client Secret | Yes | `GOCSPX-xxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Scopes**: `https://www.googleapis.com/auth/tasks`
## Available Actions
### Parameters
The ID of the task list
The title of the task
The description of the task
Mark as true if your task is already completed
Due date of the task as an RFC 3339 timestamp (date portion only)
### Response
```json
{
"$defs": {
"TaskItem": {
"additionalProperties": false,
"description": "A Google Tasks task resource.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Notes"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"due": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Due"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"self_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Link"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kind"
}
},
"title": "TaskItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"task": {
"anyOf": [
{
"$ref": "#/$defs/TaskItem"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateTaskOutput",
"type": "object"
}
```
### Parameters
The title of the task list
### Response
```json
{
"$defs": {
"TaskListItem": {
"additionalProperties": false,
"description": "A Google Tasks task list resource.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"self_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Link"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kind"
}
},
"title": "TaskListItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"task_list": {
"anyOf": [
{
"$ref": "#/$defs/TaskListItem"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateTaskListOutput",
"type": "object"
}
```
### Parameters
The ID of the task list
The ID of the task
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "DeleteTaskOutput",
"type": "object"
}
```
### Parameters
The ID of the task list
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "DeleteTaskListOutput",
"type": "object"
}
```
### Parameters
The ID of the task list
Maximum number of tasks to be fetched (Default: `20`)
Whether completed tasks are returned in the result
Whether deleted tasks are returned in the result
### Response
```json
{
"$defs": {
"TaskItem": {
"additionalProperties": false,
"description": "A Google Tasks task resource.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Notes"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"due": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Due"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"self_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Link"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kind"
}
},
"title": "TaskItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"tasks": {
"items": {
"$ref": "#/$defs/TaskItem"
},
"title": "Tasks",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListTasksOutput",
"type": "object"
}
```
### Parameters
Maximum number of task lists to be fetched (Default: `20`)
### Response
```json
{
"$defs": {
"TaskListItem": {
"additionalProperties": false,
"description": "A Google Tasks task list resource.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"self_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Link"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kind"
}
},
"title": "TaskListItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"task_lists": {
"items": {
"$ref": "#/$defs/TaskListItem"
},
"title": "Task Lists",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListTaskListsOutput",
"type": "object"
}
```
### Parameters
The ID of the task list
The ID of the task
The title of the task
The description of the task
Mark as true if your task is already completed
Due date of the task as an RFC 3339 timestamp (date portion only)
### Response
```json
{
"$defs": {
"TaskItem": {
"additionalProperties": false,
"description": "A Google Tasks task resource.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Notes"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"due": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Due"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"self_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Link"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kind"
}
},
"title": "TaskItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"task": {
"anyOf": [
{
"$ref": "#/$defs/TaskItem"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UpdateTaskOutput",
"type": "object"
}
```
### Parameters
The ID of the task list
The title of the task list
### Response
```json
{
"$defs": {
"TaskListItem": {
"additionalProperties": false,
"description": "A Google Tasks task list resource.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"self_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Link"
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Etag"
},
"kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Kind"
}
},
"title": "TaskListItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"task_list": {
"anyOf": [
{
"$ref": "#/$defs/TaskListItem"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UpdateTaskListOutput",
"type": "object"
}
```
## Limits & Quotas
- Default quota: 50,000 queries per day per project (Google Cloud project-level).
- Per-user rate limit: ~500 requests per 100 seconds.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Google Tasks](https://tasks.google.com)
---
# Google Workspace Admin Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/google-workspace
Retrieve admin audit activity reports from Google Workspace via the Admin SDK Reports API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/google_workspace/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Google Workspace Admin** to any ModuleX agent or workflow. Retrieve admin audit activity reports from Google Workspace via the Admin SDK Reports API (`admin.googleapis.com`).
**Categories**: Productivity & Collaboration · Admin · Enterprise · **Auth**: OAuth2 · **Actions**: 4
## Authentication
### OAuth2 Authentication
Connect using Google OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Google OAuth App Client ID | Yes | `xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com` |
| Client Secret | Google OAuth App Client Secret | Yes | `GOCSPX-xxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Scopes**: `https://www.googleapis.com/auth/admin.reports.audit.readonly`
## Available Actions
### Parameters
Application name to retrieve events for. Valid values: access_transparency, admin, calendar, chat, drive, gcp, gplus, groups, groups_enterprise, jamboard, login, meet, mobile, rules, saml, token, user_accounts, context_aware_access, chrome, data_studio, keep
Profile ID or email of the administrator to filter activities for
Name of the event to filter by
End of the time range in RFC 3339 format (e.g. 2010-10-28T10:26:35.000Z)
Beginning of the time range in RFC 3339 format (e.g. 2010-10-28T10:26:35.000Z)
Maximum number of activity records to return per page (default 1000)
Comma-separated event parameter filters (e.g. parameter_name relational_operator value)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"activities": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Activities",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListActivitiesByAdminOutput",
"type": "object"
}
```
### Parameters
Application name to retrieve events for. Valid values: access_transparency, admin, calendar, chat, drive, gcp, gplus, groups, groups_enterprise, jamboard, login, meet, mobile, rules, saml, token, user_accounts, context_aware_access, chrome, data_studio, keep
Name of the event to filter by
Profile ID or email of the administrator to filter activities for
End of the time range in RFC 3339 format (e.g. 2010-10-28T10:26:35.000Z)
Beginning of the time range in RFC 3339 format (e.g. 2010-10-28T10:26:35.000Z)
Maximum number of activity records to return per page (default 1000)
Comma-separated event parameter filters (e.g. parameter_name relational_operator value)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"activities": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Activities",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListActivitiesByEventAndAdminOutput",
"type": "object"
}
```
### Parameters
Application name to retrieve events for. Valid values: access_transparency, admin, calendar, chat, drive, gcp, gplus, groups, groups_enterprise, jamboard, login, meet, mobile, rules, saml, token, user_accounts, context_aware_access, chrome, data_studio, keep
Name of the event to filter by
End of the time range in RFC 3339 format (e.g. 2010-10-28T10:26:35.000Z)
Beginning of the time range in RFC 3339 format (e.g. 2010-10-28T10:26:35.000Z)
Maximum number of activity records to return per page (default 1000)
Comma-separated event parameter filters (e.g. parameter_name relational_operator value)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"activities": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Activities",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListActivitiesByEventNameOutput",
"type": "object"
}
```
### Parameters
Application name to retrieve events for. Valid values: access_transparency, admin, calendar, chat, drive, gcp, gplus, groups, groups_enterprise, jamboard, login, meet, mobile, rules, saml, token, user_accounts, context_aware_access, chrome, data_studio, keep
End of the time range in RFC 3339 format (e.g. 2010-10-28T10:26:35.000Z)
Beginning of the time range in RFC 3339 format (e.g. 2010-10-28T10:26:35.000Z)
Maximum number of activity records to return per page (default 1000)
Comma-separated event parameter filters (e.g. parameter_name relational_operator value)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"activities": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Activities",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListAllActivitiesOutput",
"type": "object"
}
```
## Limits & Quotas
- **Admin SDK Reports API quota**: 2,400 queries per minute per Google Workspace domain (default).
- **Per-user limit**: 480 queries per minute per user.
- **Error model**: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising. Plan for retries on the agent side based on the error string.
## Related integrations
## Links
- [Google Workspace Admin](https://workspace.google.com)
---
# Grafana Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/grafana
Manage Grafana dashboards, alert rules, annotations, contact points, data sources, and folders, and monitor instance and data source health via the Grafana HTTP API.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/grafana/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Grafana** to any ModuleX agent or workflow. Manage Grafana dashboards, alert rules, annotations, contact points, data sources, and folders, and monitor instance and data source health against the Grafana HTTP API of your own instance.
**Categories**: Monitoring & Observability · Monitoring · Data Analytics · **Auth**: Service Account Token · **Actions**: 25
## Authentication
### Service Account Token
Authenticate with a Grafana service account token against your instance
In Grafana, open Administration -> Users and access -> Service accounts
Create a service account with the roles your workflow needs (e.g. Editor or Admin)
Add a service account token and copy the generated 'glsa_...' value
Paste the token below and set your Grafana instance URL (e.g. https://your-grafana.com)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Service Account Token | Your Grafana service account token (starts with glsa_) | Yes | `glsa_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_xxxxxxxx` |
| Grafana URL | Your Grafana instance base URL, e.g. https://your-grafana.com | Yes | `https://your-grafana.com` |
## Available Actions
### Parameters
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
Search query to filter dashboards by title
Filter by tag (comma-separated for multiple tags)
Filter by folder UIDs (comma-separated)
Filter by dashboard UIDs (comma-separated)
Only return starred dashboards
Maximum number of dashboards to return
Page number for pagination (1-based)
### Response
```json
{
"$defs": {
"DashboardSearchResult": {
"additionalProperties": false,
"description": "A single dashboard search-result row from ``/api/search``.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"uri": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uri"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"tags": {
"items": {
"type": "string"
},
"title": "Tags",
"type": "array"
},
"is_starred": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Starred"
},
"folder_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Folder Id"
},
"folder_uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Folder Uid"
},
"folder_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Folder Title"
},
"folder_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Folder Url"
}
},
"title": "DashboardSearchResult",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"dashboards": {
"items": {
"$ref": "#/$defs/DashboardSearchResult"
},
"title": "Dashboards",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListDashboardsOutput",
"type": "object"
}
```
### Parameters
The UID of the dashboard to retrieve
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"dashboard": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Dashboard"
},
"meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Meta"
}
},
"required": [
"success"
],
"title": "GetDashboardOutput",
"type": "object"
}
```
### Parameters
The title of the new dashboard
UID of the folder to create the dashboard in
Comma-separated list of tags
Dashboard timezone (e.g. browser, utc)
Auto-refresh interval (e.g. 5s, 1m, 5m)
JSON array of panel configurations
Overwrite an existing dashboard with the same title
Commit message for the dashboard version
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"version": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Version"
},
"slug": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Slug"
}
},
"required": [
"success"
],
"title": "CreateDashboardOutput",
"type": "object"
}
```
### Parameters
The UID of the dashboard to update
New title for the dashboard
New folder UID to move the dashboard to
Comma-separated list of new tags
Dashboard timezone (e.g. browser, utc)
Auto-refresh interval (e.g. 5s, 1m, 5m)
JSON array of panel configurations
Overwrite even on a version conflict
Commit message for this version
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"version": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Version"
},
"slug": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Slug"
}
},
"required": [
"success"
],
"title": "UpdateDashboardOutput",
"type": "object"
}
```
### Parameters
The UID of the dashboard to delete
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
}
},
"required": [
"success"
],
"title": "DeleteDashboardOutput",
"type": "object"
}
```
### Parameters
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"$defs": {
"AlertRule": {
"additionalProperties": false,
"description": "A provisioned alert rule (shared by list/get/create/update).",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"condition": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Condition"
},
"data": {
"items": {},
"title": "Data",
"type": "array"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"no_data_state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "No Data State"
},
"exec_err_state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Exec Err State"
},
"for_": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "For"
},
"keep_firing_for": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Keep Firing For"
},
"missing_series_evals_to_resolve": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Missing Series Evals To Resolve"
},
"annotations": {
"additionalProperties": true,
"title": "Annotations",
"type": "object"
},
"labels": {
"additionalProperties": true,
"title": "Labels",
"type": "object"
},
"is_paused": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Paused"
},
"folder_uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Folder Uid"
},
"rule_group": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rule Group"
},
"org_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Org Id"
},
"provenance": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Provenance"
},
"notification_settings": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Notification Settings"
},
"record": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Record"
}
},
"title": "AlertRule",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"rules": {
"items": {
"$ref": "#/$defs/AlertRule"
},
"title": "Rules",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListAlertRulesOutput",
"type": "object"
}
```
### Parameters
The UID of the alert rule to retrieve
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"$defs": {
"AlertRule": {
"additionalProperties": false,
"description": "A provisioned alert rule (shared by list/get/create/update).",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"condition": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Condition"
},
"data": {
"items": {},
"title": "Data",
"type": "array"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"no_data_state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "No Data State"
},
"exec_err_state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Exec Err State"
},
"for_": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "For"
},
"keep_firing_for": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Keep Firing For"
},
"missing_series_evals_to_resolve": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Missing Series Evals To Resolve"
},
"annotations": {
"additionalProperties": true,
"title": "Annotations",
"type": "object"
},
"labels": {
"additionalProperties": true,
"title": "Labels",
"type": "object"
},
"is_paused": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Paused"
},
"folder_uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Folder Uid"
},
"rule_group": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rule Group"
},
"org_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Org Id"
},
"provenance": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Provenance"
},
"notification_settings": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Notification Settings"
},
"record": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Record"
}
},
"title": "AlertRule",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"rule": {
"anyOf": [
{
"$ref": "#/$defs/AlertRule"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetAlertRuleOutput",
"type": "object"
}
```
### Parameters
The title of the alert rule
UID of the folder to create the alert in
The name of the rule group
JSON array of query/expression data objects
RefId of the query/expression used as the alert condition (omit for recording rules)
Duration to wait before firing (e.g. 5m, 1h)
State when no data is returned (NoData, Alerting, OK)
State on execution error (Error, Alerting, OK)
JSON object of annotations
JSON object of labels
Optional custom UID for the alert rule
Whether the rule is paused on creation
Duration to keep firing after the condition stops
Missing series evaluations before resolving
JSON object of per-rule notification settings
JSON object configuring this as a recording rule
Set the X-Disable-Provenance header so the rule stays UI-editable
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"$defs": {
"AlertRule": {
"additionalProperties": false,
"description": "A provisioned alert rule (shared by list/get/create/update).",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"condition": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Condition"
},
"data": {
"items": {},
"title": "Data",
"type": "array"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"no_data_state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "No Data State"
},
"exec_err_state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Exec Err State"
},
"for_": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "For"
},
"keep_firing_for": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Keep Firing For"
},
"missing_series_evals_to_resolve": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Missing Series Evals To Resolve"
},
"annotations": {
"additionalProperties": true,
"title": "Annotations",
"type": "object"
},
"labels": {
"additionalProperties": true,
"title": "Labels",
"type": "object"
},
"is_paused": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Paused"
},
"folder_uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Folder Uid"
},
"rule_group": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rule Group"
},
"org_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Org Id"
},
"provenance": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Provenance"
},
"notification_settings": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Notification Settings"
},
"record": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Record"
}
},
"title": "AlertRule",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"rule": {
"anyOf": [
{
"$ref": "#/$defs/AlertRule"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateAlertRuleOutput",
"type": "object"
}
```
### Parameters
The UID of the alert rule to update
New title for the alert rule
New folder UID for the rule
New rule group name
New condition refId
New JSON array of query/expression data objects
Duration to wait before firing (e.g. 5m, 1h)
State when no data is returned (NoData, Alerting, OK)
State on execution error (Error, Alerting, OK)
JSON object of annotations
JSON object of labels
Whether the rule is paused
Duration to keep firing after the condition stops
Missing series evaluations before resolving
JSON object of per-rule notification settings
JSON object configuring this as a recording rule
Set the X-Disable-Provenance header so the rule stays UI-editable
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"$defs": {
"AlertRule": {
"additionalProperties": false,
"description": "A provisioned alert rule (shared by list/get/create/update).",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"condition": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Condition"
},
"data": {
"items": {},
"title": "Data",
"type": "array"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"no_data_state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "No Data State"
},
"exec_err_state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Exec Err State"
},
"for_": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "For"
},
"keep_firing_for": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Keep Firing For"
},
"missing_series_evals_to_resolve": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Missing Series Evals To Resolve"
},
"annotations": {
"additionalProperties": true,
"title": "Annotations",
"type": "object"
},
"labels": {
"additionalProperties": true,
"title": "Labels",
"type": "object"
},
"is_paused": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Paused"
},
"folder_uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Folder Uid"
},
"rule_group": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rule Group"
},
"org_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Org Id"
},
"provenance": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Provenance"
},
"notification_settings": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Notification Settings"
},
"record": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Record"
}
},
"title": "AlertRule",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"rule": {
"anyOf": [
{
"$ref": "#/$defs/AlertRule"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UpdateAlertRuleOutput",
"type": "object"
}
```
### Parameters
The UID of the alert rule to delete
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "DeleteAlertRuleOutput",
"type": "object"
}
```
### Parameters
Filter contact points by exact name match
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"$defs": {
"ContactPoint": {
"additionalProperties": false,
"description": "A single notification contact point.",
"properties": {
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"settings": {
"additionalProperties": true,
"title": "Settings",
"type": "object"
},
"disable_resolve_message": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Disable Resolve Message"
},
"provenance": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Provenance"
}
},
"title": "ContactPoint",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"contact_points": {
"items": {
"$ref": "#/$defs/ContactPoint"
},
"title": "Contact Points",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListContactPointsOutput",
"type": "object"
}
```
### Parameters
Name of the contact point
Receiver type (e.g. slack, email, pagerduty, webhook, teams, opsgenie, discord)
JSON object of type-specific receiver settings
Do not send a notification when the alert resolves
Set the X-Disable-Provenance header so the contact point stays UI-editable
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"settings": {
"additionalProperties": true,
"title": "Settings",
"type": "object"
},
"disable_resolve_message": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Disable Resolve Message"
},
"provenance": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Provenance"
}
},
"required": [
"success"
],
"title": "CreateContactPointOutput",
"type": "object"
}
```
### Parameters
The text content of the annotation
Comma-separated list of tags
UID of the dashboard to annotate; omit for a global annotation
ID of the panel to attach the annotation to
Start time in epoch milliseconds (defaults to now)
End time in epoch milliseconds for range annotations
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "CreateAnnotationOutput",
"type": "object"
}
```
### Parameters
Start time in epoch milliseconds
End time in epoch milliseconds
Dashboard UID to query annotations from
Legacy numeric dashboard ID filter
Filter by panel ID
Filter by alert ID
Filter by ID of the creating user
Comma-separated list of tags to filter by
Filter by type (alert or annotation)
Maximum number of annotations to return
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"$defs": {
"Annotation": {
"additionalProperties": false,
"description": "A single annotation row from ``/api/annotations``.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"alert_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Alert Id"
},
"dashboard_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Dashboard Id"
},
"dashboard_uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Dashboard Uid"
},
"panel_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Panel Id"
},
"user_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "User Id"
},
"user_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User Name"
},
"new_state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "New State"
},
"prev_state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Prev State"
},
"time": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Time"
},
"time_end": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Time End"
},
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
},
"metric": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Metric"
},
"tags": {
"items": {
"type": "string"
},
"title": "Tags",
"type": "array"
},
"data": {
"additionalProperties": true,
"title": "Data",
"type": "object"
}
},
"title": "Annotation",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"annotations": {
"items": {
"$ref": "#/$defs/Annotation"
},
"title": "Annotations",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListAnnotationsOutput",
"type": "object"
}
```
### Parameters
The ID of the annotation to update
New text content for the annotation
Comma-separated list of new tags
New start time in epoch milliseconds
New end time in epoch milliseconds
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "UpdateAnnotationOutput",
"type": "object"
}
```
### Parameters
The ID of the annotation to delete
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "DeleteAnnotationOutput",
"type": "object"
}
```
### Parameters
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"$defs": {
"DataSource": {
"additionalProperties": false,
"description": "A single data source from ``/api/datasources``.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"org_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Org Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"type_logo_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type Logo Url"
},
"access": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Access"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"user": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User"
},
"database": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Database"
},
"basic_auth": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Basic Auth"
},
"basic_auth_user": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Basic Auth User"
},
"with_credentials": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "With Credentials"
},
"is_default": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Default"
},
"json_data": {
"additionalProperties": true,
"title": "Json Data",
"type": "object"
},
"secure_json_fields": {
"additionalProperties": true,
"title": "Secure Json Fields",
"type": "object"
},
"version": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Version"
},
"read_only": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Read Only"
}
},
"title": "DataSource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data_sources": {
"items": {
"$ref": "#/$defs/DataSource"
},
"title": "Data Sources",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListDataSourcesOutput",
"type": "object"
}
```
### Parameters
The ID or UID of the data source to retrieve
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"$defs": {
"DataSource": {
"additionalProperties": false,
"description": "A single data source from ``/api/datasources``.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"org_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Org Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"type_logo_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type Logo Url"
},
"access": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Access"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"user": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User"
},
"database": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Database"
},
"basic_auth": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Basic Auth"
},
"basic_auth_user": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Basic Auth User"
},
"with_credentials": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "With Credentials"
},
"is_default": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Default"
},
"json_data": {
"additionalProperties": true,
"title": "Json Data",
"type": "object"
},
"secure_json_fields": {
"additionalProperties": true,
"title": "Secure Json Fields",
"type": "object"
},
"version": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Version"
},
"read_only": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Read Only"
}
},
"title": "DataSource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data_source": {
"anyOf": [
{
"$ref": "#/$defs/DataSource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetDataSourceOutput",
"type": "object"
}
```
### Parameters
The UID of the data source to health-check
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "CheckDataSourceHealthOutput",
"type": "object"
}
```
### Parameters
Maximum number of folders to return
Page number for pagination
List children of this folder UID
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"$defs": {
"Folder": {
"additionalProperties": false,
"description": "A single folder from ``/api/folders``.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"parent_uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Parent Uid"
},
"parents": {
"items": {
"$ref": "#/$defs/FolderParent"
},
"title": "Parents",
"type": "array"
},
"has_acl": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has Acl"
},
"can_save": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Save"
},
"can_edit": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Edit"
},
"can_admin": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Admin"
},
"created_by": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created By"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated_by": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated By"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"version": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Version"
}
},
"title": "Folder",
"type": "object"
},
"FolderParent": {
"additionalProperties": false,
"description": "An ancestor folder entry (nested folders only).",
"properties": {
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
}
},
"title": "FolderParent",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"folders": {
"items": {
"$ref": "#/$defs/Folder"
},
"title": "Folders",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListFoldersOutput",
"type": "object"
}
```
### Parameters
The title of the new folder
Optional UID for the folder
Parent folder UID for nested folders
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"$defs": {
"Folder": {
"additionalProperties": false,
"description": "A single folder from ``/api/folders``.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"parent_uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Parent Uid"
},
"parents": {
"items": {
"$ref": "#/$defs/FolderParent"
},
"title": "Parents",
"type": "array"
},
"has_acl": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has Acl"
},
"can_save": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Save"
},
"can_edit": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Edit"
},
"can_admin": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Admin"
},
"created_by": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created By"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated_by": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated By"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"version": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Version"
}
},
"title": "Folder",
"type": "object"
},
"FolderParent": {
"additionalProperties": false,
"description": "An ancestor folder entry (nested folders only).",
"properties": {
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
}
},
"title": "FolderParent",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"folder": {
"anyOf": [
{
"$ref": "#/$defs/Folder"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateFolderOutput",
"type": "object"
}
```
### Parameters
The UID of the folder to retrieve
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"$defs": {
"Folder": {
"additionalProperties": false,
"description": "A single folder from ``/api/folders``.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"parent_uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Parent Uid"
},
"parents": {
"items": {
"$ref": "#/$defs/FolderParent"
},
"title": "Parents",
"type": "array"
},
"has_acl": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has Acl"
},
"can_save": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Save"
},
"can_edit": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Edit"
},
"can_admin": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Admin"
},
"created_by": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created By"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated_by": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated By"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"version": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Version"
}
},
"title": "Folder",
"type": "object"
},
"FolderParent": {
"additionalProperties": false,
"description": "An ancestor folder entry (nested folders only).",
"properties": {
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
}
},
"title": "FolderParent",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"folder": {
"anyOf": [
{
"$ref": "#/$defs/Folder"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetFolderOutput",
"type": "object"
}
```
### Parameters
The UID of the folder to update
New title for the folder
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"$defs": {
"Folder": {
"additionalProperties": false,
"description": "A single folder from ``/api/folders``.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"parent_uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Parent Uid"
},
"parents": {
"items": {
"$ref": "#/$defs/FolderParent"
},
"title": "Parents",
"type": "array"
},
"has_acl": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has Acl"
},
"can_save": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Save"
},
"can_edit": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Edit"
},
"can_admin": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Admin"
},
"created_by": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created By"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated_by": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated By"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"version": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Version"
}
},
"title": "Folder",
"type": "object"
},
"FolderParent": {
"additionalProperties": false,
"description": "An ancestor folder entry (nested folders only).",
"properties": {
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
}
},
"title": "FolderParent",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"folder": {
"anyOf": [
{
"$ref": "#/$defs/Folder"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UpdateFolderOutput",
"type": "object"
}
```
### Parameters
The UID of the folder to delete
Delete any alert rules stored in the folder along with it
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "DeleteFolderOutput",
"type": "object"
}
```
### Parameters
Organization ID for multi-org Grafana instances (e.g. 1, 2). Sent as the X-Grafana-Org-Id header when set.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"commit": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Commit"
},
"database": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Database"
},
"version": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Version"
}
},
"required": [
"success"
],
"title": "GetHealthOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limits** are configured per Grafana instance; self-hosted
instances are unbounded by default, while Grafana Cloud applies tier
limits.
- **Update semantics**: `update_dashboard`, `update_alert_rule`, and
`update_folder` first `GET` the current resource, merge your changes,
and write the full body back (Grafana's update endpoints require the
complete resource and a version for conflict detection).
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising. Plan for
retries on the agent side based on the error string.
## Related integrations
## Links
- [Grafana](https://grafana.com)
---
# Grain Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/grain
Access Grain meeting recordings, transcripts, highlights, and AI-generated summaries. List and retrieve recordings with flexible filters, fetch full transcripts, browse teams, meeting types, and views, and manage webhook subscriptions for recording events.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/grain/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Grain** to any ModuleX agent or workflow. Access Grain meeting recordings, transcripts, highlights, and AI-generated summaries through the Grain public REST API (`api.grain.com/_/public-api`). List and retrieve recordings, fetch full transcripts, browse teams, meeting types, and views, and manage webhook subscriptions for recording events.
**Categories**: Productivity & Collaboration · Meeting · Note Taking · **Auth**: API Key · **Actions**: 9
## Authentication
### API Key Authentication
Authenticate using your Grain personal access token
Log in to your Grain account at https://grain.com
Open Settings and navigate to the API / Integrations section
Create a Personal Access Token (developer access may require approval)
Paste the access token below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Grain API Key | Your Grain personal access token | Yes | `-` |
## Available Actions
### Parameters
Pagination cursor for next page (returned from previous response)
Only recordings before this ISO8601 timestamp (e.g., "2024-01-15T00:00:00Z")
Only recordings after this ISO8601 timestamp (e.g., "2024-01-01T00:00:00Z")
Filter: "internal" or "external"
Search term to filter by recording title (e.g., "weekly standup")
Filter by team UUID
Filter by meeting type UUID
Include highlights/clips in response (Default: `false`)
Include participant list in response (Default: `false`)
Include AI-generated summary (Default: `false`)
### Response
```json
{
"$defs": {
"Recording": {
"additionalProperties": false,
"description": "A meeting recording object.\n\nExtra include-blocks (highlights, participants, ai_summary,\ncalendar_event, hubspot, etc.) are returned verbatim as\nJSON-serializable values.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"start_datetime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Start Datetime"
},
"end_datetime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "End Datetime"
},
"duration_ms": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Duration Ms"
},
"media_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Media Type"
},
"source": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Source"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"thumbnail_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Thumbnail Url"
},
"tags": {
"items": {
"type": "string"
},
"title": "Tags",
"type": "array"
},
"teams": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Teams",
"type": "array"
},
"meeting_type": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Meeting Type"
},
"highlights": {
"anyOf": [
{
"items": {
"additionalProperties": true,
"type": "object"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Highlights"
},
"participants": {
"anyOf": [
{
"items": {
"additionalProperties": true,
"type": "object"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Participants"
},
"ai_summary": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Ai Summary"
},
"calendar_event": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Calendar Event"
},
"hubspot": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Hubspot"
},
"private_notes": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Private Notes"
},
"ai_template_sections": {
"anyOf": [
{
"items": {
"additionalProperties": true,
"type": "object"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Ai Template Sections"
}
},
"title": "Recording",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"recordings": {
"items": {
"$ref": "#/$defs/Recording"
},
"title": "Recordings",
"type": "array"
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cursor"
}
},
"required": [
"success"
],
"title": "ListRecordingsOutput",
"type": "object"
}
```
### Parameters
The recording UUID
Include highlights/clips (Default: `false`)
Include participant list (Default: `false`)
Include AI summary (Default: `false`)
Include calendar event data (Default: `false`)
Include HubSpot associations (Default: `false`)
### Response
```json
{
"$defs": {
"Recording": {
"additionalProperties": false,
"description": "A meeting recording object.\n\nExtra include-blocks (highlights, participants, ai_summary,\ncalendar_event, hubspot, etc.) are returned verbatim as\nJSON-serializable values.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"start_datetime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Start Datetime"
},
"end_datetime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "End Datetime"
},
"duration_ms": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Duration Ms"
},
"media_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Media Type"
},
"source": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Source"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"thumbnail_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Thumbnail Url"
},
"tags": {
"items": {
"type": "string"
},
"title": "Tags",
"type": "array"
},
"teams": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Teams",
"type": "array"
},
"meeting_type": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Meeting Type"
},
"highlights": {
"anyOf": [
{
"items": {
"additionalProperties": true,
"type": "object"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Highlights"
},
"participants": {
"anyOf": [
{
"items": {
"additionalProperties": true,
"type": "object"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Participants"
},
"ai_summary": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Ai Summary"
},
"calendar_event": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Calendar Event"
},
"hubspot": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Hubspot"
},
"private_notes": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Private Notes"
},
"ai_template_sections": {
"anyOf": [
{
"items": {
"additionalProperties": true,
"type": "object"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Ai Template Sections"
}
},
"title": "Recording",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"recording": {
"anyOf": [
{
"$ref": "#/$defs/Recording"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetRecordingOutput",
"type": "object"
}
```
### Parameters
The recording UUID
### Response
```json
{
"$defs": {
"TranscriptSection": {
"additionalProperties": false,
"description": "A single transcript section (speaker turn).",
"properties": {
"participant_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Participant Id"
},
"speaker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Speaker"
},
"start": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Start"
},
"end": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "End"
},
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
}
},
"title": "TranscriptSection",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"transcript": {
"items": {
"$ref": "#/$defs/TranscriptSection"
},
"title": "Transcript",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetTranscriptOutput",
"type": "object"
}
```
### Parameters
Optional view type filter: recordings, highlights, or stories
### Response
```json
{
"$defs": {
"View": {
"additionalProperties": false,
"description": "A Grain view object.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
}
},
"title": "View",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"views": {
"items": {
"$ref": "#/$defs/View"
},
"title": "Views",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListViewsOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"Team": {
"additionalProperties": false,
"description": "A team object.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
}
},
"title": "Team",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"teams": {
"items": {
"$ref": "#/$defs/Team"
},
"title": "Teams",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListTeamsOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"MeetingType": {
"additionalProperties": false,
"description": "A meeting type object.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"scope": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Scope"
}
},
"title": "MeetingType",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"meeting_types": {
"items": {
"$ref": "#/$defs/MeetingType"
},
"title": "Meeting Types",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListMeetingTypesOutput",
"type": "object"
}
```
### Parameters
Webhook endpoint URL (e.g., "https://example.com/webhooks/grain")
Grain view ID for the webhook subscription
Optional list of actions to subscribe to: added, updated, removed
### Response
```json
{
"$defs": {
"Hook": {
"additionalProperties": false,
"description": "A webhook subscription object.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Enabled"
},
"version": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Version"
},
"hook_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hook Url"
},
"view_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "View Id"
},
"actions": {
"items": {
"type": "string"
},
"title": "Actions",
"type": "array"
},
"inserted_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Inserted At"
}
},
"title": "Hook",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"hook": {
"anyOf": [
{
"$ref": "#/$defs/Hook"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateHookOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"Hook": {
"additionalProperties": false,
"description": "A webhook subscription object.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Enabled"
},
"version": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Version"
},
"hook_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hook Url"
},
"view_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "View Id"
},
"actions": {
"items": {
"type": "string"
},
"title": "Actions",
"type": "array"
},
"inserted_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Inserted At"
}
},
"title": "Hook",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"hooks": {
"items": {
"$ref": "#/$defs/Hook"
},
"title": "Hooks",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListHooksOutput",
"type": "object"
}
```
### Parameters
The hook UUID to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "DeleteHookOutput",
"type": "object"
}
```
## Limits & Quotas
- The Grain public API requires the `Public-Api-Version` header
(currently `2025-10-31`) on the recording, transcript, team, and
meeting-type endpoints.
- Developer access to the public API is in beta and may be limited to
approved partners.
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising. Plan for
retries on the agent side based on the error string.
## Related integrations
## Links
- [Grain](https://grain.com)
---
# Granola Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/granola
Retrieve meeting notes, summaries, attendees, calendar details, and transcripts from Granola.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/granola/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Granola** to any ModuleX agent or workflow. Retrieve meeting notes, summaries, attendees, calendar event details, and transcripts from Granola through its REST API (`public-api.granola.ai`).
**Categories**: Productivity & Collaboration · Meeting · Note Taking · **Auth**: API Key · **Actions**: 3
## Authentication
### API Key Authentication
Authenticate using your Granola API key
Open Granola and go to Settings (a Business plan is required)
Navigate to the API / Developer section
Create a new API key and copy it
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Granola API Key | Your Granola API key | Yes | `grn_xxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
Return notes created before this date (ISO 8601)
Return notes created after this date (ISO 8601)
Return notes updated after this date (ISO 8601)
Return notes in this folder and its child folders (e.g., fol_4y6LduVdwSKC27)
Pagination cursor from a previous response
Number of notes per page (1-30, default 10)
### Response
```json
{
"$defs": {
"NoteSummary": {
"additionalProperties": false,
"description": "A single note row in ``list_notes``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"owner_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Owner Name"
},
"owner_email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Owner Email"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"title": "NoteSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"notes": {
"items": {
"$ref": "#/$defs/NoteSummary"
},
"title": "Notes",
"type": "array"
},
"has_more": {
"default": false,
"title": "Has More",
"type": "boolean"
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cursor"
}
},
"required": [
"success"
],
"title": "ListNotesOutput",
"type": "object"
}
```
### Parameters
The note ID (e.g., not_1d3tmYTlCICgjy)
Whether to include the meeting transcript (Default: `false`)
### Response
```json
{
"$defs": {
"Attendee": {
"additionalProperties": false,
"description": "A meeting attendee in ``get_note``.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
}
},
"title": "Attendee",
"type": "object"
},
"FolderRef": {
"additionalProperties": false,
"description": "A folder reference.\n\nUsed both for a note's folder memberships in ``get_note`` (id, name)\nand for the workspace folder listing in ``list_folders``\n(id, name, parent_folder_id).",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"parent_folder_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Parent Folder Id"
}
},
"title": "FolderRef",
"type": "object"
},
"TranscriptSegment": {
"additionalProperties": false,
"description": "A single transcript entry in ``get_note``.",
"properties": {
"speaker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Speaker"
},
"speaker_label": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Speaker Label"
},
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
},
"start_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Start Time"
},
"end_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "End Time"
}
},
"title": "TranscriptSegment",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"owner_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Owner Name"
},
"owner_email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Owner Email"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"web_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web Url"
},
"summary_text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary Text"
},
"summary_markdown": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary Markdown"
},
"attendees": {
"items": {
"$ref": "#/$defs/Attendee"
},
"title": "Attendees",
"type": "array"
},
"folders": {
"items": {
"$ref": "#/$defs/FolderRef"
},
"title": "Folders",
"type": "array"
},
"calendar_event_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Calendar Event Title"
},
"calendar_organiser": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Calendar Organiser"
},
"calendar_event_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Calendar Event Id"
},
"scheduled_start_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Scheduled Start Time"
},
"scheduled_end_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Scheduled End Time"
},
"invitees": {
"items": {
"type": "string"
},
"title": "Invitees",
"type": "array"
},
"transcript": {
"anyOf": [
{
"items": {
"$ref": "#/$defs/TranscriptSegment"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Transcript"
}
},
"required": [
"success"
],
"title": "GetNoteOutput",
"type": "object"
}
```
### Parameters
Pagination cursor from a previous response
Number of folders per page (1-30, default 10)
### Response
```json
{
"$defs": {
"FolderRef": {
"additionalProperties": false,
"description": "A folder reference.\n\nUsed both for a note's folder memberships in ``get_note`` (id, name)\nand for the workspace folder listing in ``list_folders``\n(id, name, parent_folder_id).",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"parent_folder_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Parent Folder Id"
}
},
"title": "FolderRef",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"folders": {
"items": {
"$ref": "#/$defs/FolderRef"
},
"title": "Folders",
"type": "array"
},
"has_more": {
"default": false,
"title": "Has More",
"type": "boolean"
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cursor"
}
},
"required": [
"success"
],
"title": "ListFoldersOutput",
"type": "object"
}
```
## Limits & Quotas
- The API only returns notes that have a generated AI summary and
transcript; notes still processing or never summarized are omitted
from list responses and return `404` on direct access.
- `page_size` accepts `1-30` (default `10`) for `list_notes` and
`list_folders`.
- Rate limits are applied per user or workspace depending on the key's
access scope; exceeding them returns `429 Too Many Requests`.
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising. Plan for
retries on the agent side based on the error string.
## Related integrations
## Links
- [Granola](https://granola.ai)
---
# Greptile Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/greptile
Query and search codebases using natural language with Greptile. Get AI-generated answers about your code, find relevant files, and understand complex codebases.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/greptile/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Greptile** to any ModuleX agent or workflow. AI-powered codebase search and Q&A against the Greptile v2 REST API (`api.greptile.com`). Query and search codebases using natural language, get AI-generated answers about your code with cited file references, index repositories, and check indexing status.
**Categories**: Developer Tools & Infrastructure · Version Control · Knowledge Base · **Auth**: API Key · **Actions**: 4
## Authentication
### API Key Authentication
Authenticate using your Greptile API key plus a GitHub Personal Access Token so Greptile can access your repositories
Go to https://app.greptile.com and sign up or log in
Open Settings and create a new API key
Paste the Greptile API key below
Create a GitHub Personal Access Token with 'repo' read access at https://github.com/settings/tokens and paste it as the GitHub token
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Greptile API Key | Your Greptile API key from app.greptile.com | Yes | `-` |
| GitHub Token | A GitHub Personal Access Token with 'repo' read access, used by Greptile to clone and index your repositories | Yes | `-` |
## Available Actions
### Parameters
Natural language question about the codebase
Comma-separated list of repositories. Format: 'github:branch:owner/repo' or just 'owner/repo' (defaults to github:main). Example: 'facebook/react' or 'github:main:facebook/react,github:main:facebook/relay'
Optional session ID for conversation continuity across multiple queries
Enable genius mode for more thorough analysis (slower but more accurate)
### Response
```json
{
"$defs": {
"QuerySource": {
"additionalProperties": false,
"description": "A single code reference returned by ``query`` and ``search``.",
"properties": {
"repository": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Repository"
},
"remote": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Remote"
},
"branch": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Branch"
},
"filepath": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Filepath"
},
"linestart": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Linestart"
},
"lineend": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Lineend"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"distance": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Distance"
}
},
"title": "QuerySource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"sources": {
"items": {
"$ref": "#/$defs/QuerySource"
},
"title": "Sources",
"type": "array"
}
},
"required": [
"success"
],
"title": "QueryOutput",
"type": "object"
}
```
### Parameters
Natural language search query to find relevant code
Comma-separated list of repositories. Format: 'github:branch:owner/repo' or just 'owner/repo' (defaults to github:main). Example: 'facebook/react' or 'github:main:facebook/react,github:main:facebook/relay'
Optional session ID for conversation continuity across multiple searches
Enable genius mode for more thorough search (slower but more accurate)
### Response
```json
{
"$defs": {
"QuerySource": {
"additionalProperties": false,
"description": "A single code reference returned by ``query`` and ``search``.",
"properties": {
"repository": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Repository"
},
"remote": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Remote"
},
"branch": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Branch"
},
"filepath": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Filepath"
},
"linestart": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Linestart"
},
"lineend": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Lineend"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"distance": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Distance"
}
},
"title": "QuerySource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"sources": {
"items": {
"$ref": "#/$defs/QuerySource"
},
"title": "Sources",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchOutput",
"type": "object"
}
```
### Parameters
Git remote type: 'github' or 'gitlab' (Default: `github`)
Repository in owner/repo format. Example: 'facebook/react'
Branch to index (e.g. 'main' or 'master')
Force re-indexing even if already indexed
Send email notification when indexing completes
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"repository_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Repository Id"
},
"status_endpoint": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status Endpoint"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "IndexRepositoryOutput",
"type": "object"
}
```
### Parameters
Git remote type: 'github' or 'gitlab' (Default: `github`)
Repository in owner/repo format. Example: 'facebook/react'
Branch name (e.g. 'main' or 'master')
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"repository": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Repository"
},
"remote": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Remote"
},
"branch": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Branch"
},
"private": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Private"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"files_processed": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Files Processed"
},
"num_files": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Num Files"
},
"sample_questions": {
"items": {
"type": "string"
},
"title": "Sample Questions",
"type": "array"
},
"sha": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sha"
},
"raw": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Raw"
}
},
"required": [
"success"
],
"title": "StatusOutput",
"type": "object"
}
```
## Limits & Quotas
- Indexing is asynchronous: small repositories take 3–5 minutes, larger ones
can take over an hour. Use `index_repo` to start indexing, then poll
`status` until it reports `completed`.
- **Error model**: non-2xx responses and timeouts are caught and returned as
`success=False` + `error` rather than raising. Plan retries on the agent
side based on the error string.
## Related integrations
## Links
- [Greptile](https://www.greptile.com)
---
# Hacker News Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/hackernews
Access Hacker News content including top stories, new posts, Ask HN, Show HN, job postings, and search functionality for stories and comments.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/hackernews/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Hacker News** to any ModuleX agent or workflow. Read-only access to the official Hacker News JSON API (`hacker-news.firebaseio.com/v0`) plus keyword search backed by `hnrss.org` RSS feeds.
**Categories**: Social Media · News · Social · Technology · Community · **Auth**: ModuleX Managed Key · **Actions**: 10
## Authentication
### ModuleX Managed Key
Use ModuleX's managed access (Hacker News API is public, no authentication required)
## Available Actions
### Parameters
Keyword to search for in story titles. Leave empty to get all new stories. (Default: ``)
Maximum number of stories to return (1-50) (Default: `10`)
Minimum points threshold for stories
Minimum comments threshold for stories
### Response
```json
{
"$defs": {
"HNRSSItem": {
"additionalProperties": false,
"properties": {
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Link"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"pub_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Pub Date"
},
"guid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Guid"
},
"author": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Author"
},
"comments_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Comments Url"
}
},
"title": "HNRSSItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"stories": {
"items": {
"$ref": "#/$defs/HNRSSItem"
},
"title": "Stories",
"type": "array"
},
"comments": {
"items": {
"$ref": "#/$defs/HNRSSItem"
},
"title": "Comments",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"keyword": {
"default": "",
"title": "Keyword",
"type": "string"
},
"source": {
"default": "hnrss.org",
"title": "Source",
"type": "string"
}
},
"required": [
"success"
],
"title": "SearchOutput",
"type": "object"
}
```
### Parameters
Keyword to search for in comments. Leave empty to get all new comments. (Default: ``)
Maximum number of comments to return (1-50) (Default: `10`)
### Response
```json
{
"$defs": {
"HNRSSItem": {
"additionalProperties": false,
"properties": {
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Link"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"pub_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Pub Date"
},
"guid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Guid"
},
"author": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Author"
},
"comments_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Comments Url"
}
},
"title": "HNRSSItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"stories": {
"items": {
"$ref": "#/$defs/HNRSSItem"
},
"title": "Stories",
"type": "array"
},
"comments": {
"items": {
"$ref": "#/$defs/HNRSSItem"
},
"title": "Comments",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"keyword": {
"default": "",
"title": "Keyword",
"type": "string"
},
"source": {
"default": "hnrss.org",
"title": "Source",
"type": "string"
}
},
"required": [
"success"
],
"title": "SearchOutput",
"type": "object"
}
```
### Parameters
Number of stories to return (1-100) (Default: `10`)
Whether to fetch full story details or just IDs (Default: `true`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"stories": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Stories",
"type": "array"
},
"story_ids": {
"items": {
"type": "integer"
},
"title": "Story Ids",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
}
},
"required": [
"success"
],
"title": "GetStoriesOutput",
"type": "object"
}
```
### Parameters
Number of stories to return (1-100) (Default: `10`)
Whether to fetch full story details or just IDs (Default: `true`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"stories": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Stories",
"type": "array"
},
"story_ids": {
"items": {
"type": "integer"
},
"title": "Story Ids",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
}
},
"required": [
"success"
],
"title": "GetStoriesOutput",
"type": "object"
}
```
### Parameters
Number of stories to return (1-100) (Default: `10`)
Whether to fetch full story details or just IDs (Default: `true`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"stories": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Stories",
"type": "array"
},
"story_ids": {
"items": {
"type": "integer"
},
"title": "Story Ids",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
}
},
"required": [
"success"
],
"title": "GetStoriesOutput",
"type": "object"
}
```
### Parameters
Number of stories to return (1-100) (Default: `10`)
Whether to fetch full story details or just IDs (Default: `true`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"stories": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Stories",
"type": "array"
},
"story_ids": {
"items": {
"type": "integer"
},
"title": "Story Ids",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
}
},
"required": [
"success"
],
"title": "GetStoriesOutput",
"type": "object"
}
```
### Parameters
Number of stories to return (1-100) (Default: `10`)
Whether to fetch full story details or just IDs (Default: `true`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"stories": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Stories",
"type": "array"
},
"story_ids": {
"items": {
"type": "integer"
},
"title": "Story Ids",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
}
},
"required": [
"success"
],
"title": "GetStoriesOutput",
"type": "object"
}
```
### Parameters
Number of stories to return (1-100) (Default: `10`)
Whether to fetch full story details or just IDs (Default: `true`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"stories": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Stories",
"type": "array"
},
"story_ids": {
"items": {
"type": "integer"
},
"title": "Story Ids",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
}
},
"required": [
"success"
],
"title": "GetStoriesOutput",
"type": "object"
}
```
### Parameters
The ID of the item to fetch
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"item": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Item"
},
"item_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Item Id"
}
},
"required": [
"success"
],
"title": "GetItemOutput",
"type": "object"
}
```
### Parameters
The HN username to look up
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"user": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "User"
},
"username": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Username"
}
},
"required": [
"success"
],
"title": "GetUserOutput",
"type": "object"
}
```
## Limits & Quotas
- `fetch_details=False` returns only the ID list (one HTTP call instead
of N+1). `fetch_details=True` issues one detail call per item, capped
at `limit`.
- `max_results` is capped at 50 on the RSS endpoints (hnrss.org cap).
- Failures and parse errors surface as `success=False` with `error`.
## Related integrations
## Links
- [Hacker News](https://news.ycombinator.com)
---
# Heroku Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/heroku
Cloud platform for building, deploying, and managing applications
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/heroku/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Heroku** to any ModuleX agent or workflow. Cloud platform for building, deploying, and managing applications via the Heroku Platform API (`api.heroku.com`).
**Categories**: Developer Tools & Infrastructure · Cloud Infrastructure · Paas · **Auth**: OAuth2 · **Actions**: 1
## Authentication
### OAuth2 Authentication
Connect using Heroku OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Heroku OAuth App Client ID | Yes | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
| Client Secret | Heroku OAuth App Client Secret | Yes | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://id.heroku.com/oauth/authorize`
- **Token URL**: `https://id.heroku.com/oauth/token`
- **Scopes**: `global`
## Available Actions
### Response
```json
{
"$defs": {
"AppSummary": {
"additionalProperties": false,
"description": "A Heroku app summary.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"web_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web Url"
},
"region": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Region"
},
"stack": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Stack"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"title": "AppSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"apps": {
"items": {
"$ref": "#/$defs/AppSummary"
},
"title": "Apps",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListAppsOutput",
"type": "object"
}
```
## Limits & Quotas
- Heroku Platform API rate limit: 4,500 requests per hour per OAuth token.
- Rate limit headers: `RateLimit-Remaining` and `RateLimit-Reset` are returned
on every response.
- Error model: non-2xx responses raise (Pattern A). The caller receives an
`httpx.HTTPStatusError` surfaced by the modulex runtime.
## Related integrations
## Links
- [Heroku](https://www.heroku.com)
---
# HeyGen Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/heygen
AI video generation platform for creating talking avatar videos
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/heygen/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **HeyGen** to any ModuleX agent or workflow. AI video generation platform for creating talking avatar videos via the HeyGen REST API (`api.heygen.com`).
**Categories**: AI & Machine Learning · AI · Video · Content Creation · **Auth**: API Key · **Actions**: 5
## Authentication
### API Key Authentication
Authenticate using your HeyGen API key
Go to https://app.heygen.com and sign in
Navigate to Settings > API
Copy your API key
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| HeyGen API Key | Your HeyGen API key from app.heygen.com/settings | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
Identifier of the talking photo to use
The text that the character will speak
Identifier of the voice to use
Title of the video
Set to true to use test mode (no credits charged, watermark added)
Set to true to create video with captions
Talking photo scale, value between 0 and 2.0 (default 1.0)
Talking photo crop style: square, circle
Talking photo talking style: stable, expressive
Talking photo expression style: default, happy
Whether to enhance the photo image
Whether to apply matting to the photo
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"video_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Video Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
}
},
"required": [
"success"
],
"title": "CreateTalkingPhotoOutput",
"type": "object"
}
```
### Parameters
Identifier of the template to use
Title of the video
Set to true to use test mode (no credits charged, watermark added)
Set to true to create video with captions
Template variable overrides as a JSON object where keys are variable names and values are objects with variable properties
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"video_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Video Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
}
},
"required": [
"success"
],
"title": "CreateVideoFromTemplateOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"events": {
"items": {
"type": "string"
},
"title": "Events",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListCustomEventsOptionsOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"VoiceInfo": {
"additionalProperties": false,
"description": "A voice entry returned by the list voices endpoint.",
"properties": {
"voice_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Voice Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
}
},
"title": "VoiceInfo",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"voices": {
"items": {
"$ref": "#/$defs/VoiceInfo"
},
"title": "Voices",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListVoiceIdOptionsOutput",
"type": "object"
}
```
### Parameters
Identifier of the HeyGen video to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"video_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Video Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"video_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Video Url"
},
"thumbnail_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Thumbnail Url"
},
"duration": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Duration"
},
"caption_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Caption Url"
}
},
"required": [
"success"
],
"title": "RetrieveVideoLinkOutput",
"type": "object"
}
```
## Limits & Quotas
- Rate limits depend on your HeyGen plan tier (Starter, Business, Enterprise).
- Video generation consumes credits; use `test=true` to avoid credit charges during development.
- No documented per-minute rate limit; excessive requests may trigger throttling.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [HeyGen](https://www.heygen.com)
---
# Hootsuite Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/hootsuite
Social media management platform for scheduling posts and managing profiles
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/hootsuite/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Hootsuite** to any ModuleX agent or workflow. Social media management platform for scheduling posts and managing profiles via the Hootsuite REST API (`platform.hootsuite.com/v1`).
**Categories**: Social Media · Marketing · **Auth**: OAuth2 · **Actions**: 4
## Authentication
### OAuth2 Authentication
Connect using Hootsuite OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Hootsuite OAuth App Client ID | Yes | `-` |
| Client Secret | Hootsuite OAuth App Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://platform.hootsuite.com/oauth2/auth`
- **Token URL**: `https://platform.hootsuite.com/oauth2/token`
- **Scopes**: `offline`
## Available Actions
### Parameters
The size of the file in bytes
The MIME type of the file (e.g. image/png, image/jpeg, video/mp4)
A publicly-accessible URL to the file to upload
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"file_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "File Id"
}
},
"required": [
"success"
],
"title": "CreateMediaUploadJobOutput",
"type": "object"
}
```
### Parameters
The ID of the media file to check status for
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"download_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Download Url"
},
"thumbnail_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Thumbnail Url"
}
},
"required": [
"success"
],
"title": "GetMediaUploadStatusOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"SocialProfile": {
"additionalProperties": false,
"description": "A Hootsuite social profile.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"social_network_username": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Social Network Username"
},
"social_network_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Social Network Id"
}
},
"title": "SocialProfile",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"profiles": {
"items": {
"$ref": "#/$defs/SocialProfile"
},
"title": "Profiles",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListSocialProfilesOutput",
"type": "object"
}
```
### Parameters
The message text to publish
Array of social profile ID strings to post to (use list_social_profiles to discover IDs)
ISO-8601 UTC time to send the message (must end with 'Z'). If omitted, sends immediately.
Array of ow.ly media URLs to attach to the message
Array of media IDs from create_media_upload_job to attach
Array of Hootsuite message tags to apply (case sensitive)
Array of webhook URLs to call when message state changes
Targeting object for Facebook Page and LinkedIn Company posts. See Hootsuite API docs for structure.
Privacy settings object with optional facebook.visibility and linkedIn.visibility arrays
Latitude in decimal degrees (-90 to 90)
Longitude in decimal degrees (-180 to 180)
Whether to send email notification when the message is published
### Response
```json
{
"$defs": {
"ScheduledMessage": {
"additionalProperties": false,
"description": "A scheduled message returned by the Hootsuite API.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
},
"scheduled_send_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Scheduled Send Time"
}
},
"title": "ScheduledMessage",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"messages": {
"items": {
"$ref": "#/$defs/ScheduledMessage"
},
"title": "Messages",
"type": "array"
}
},
"required": [
"success"
],
"title": "ScheduleMessageOutput",
"type": "object"
}
```
## Limits & Quotas
- Hootsuite API rate limits vary by plan tier; consult your account's developer dashboard for current limits.
- Free/Professional plans have lower API access thresholds than Enterprise plans.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Hootsuite](https://hootsuite.com)
---
# HubSpot Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/hubspot
HubSpot CRM integration: contacts, companies, deals, tickets, and engagement (note/task/meeting) management. Uses the hubspot-api-client SDK.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/hubspot/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **HubSpot** to any ModuleX agent or workflow. HubSpot CRM integration via the **synchronous** `hubspot-api-client` SDK. 26 actions across contacts, companies, deals, tickets, plus engagement (note/task/meeting) and property management.
**Categories**: CRM · Sales · Marketing · **Auth**: OAuth2, Private App Access Token · **Actions**: 26
## Authentication
### OAuth2 Authentication
Connect using HubSpot OAuth (recommended for most use cases)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | HubSpot OAuth App Client ID | Yes | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
| Client Secret | HubSpot OAuth App Client Secret | Yes | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://app.hubspot.com/oauth/authorize`
- **Token URL**: `https://api.hubapi.com/oauth/v1/token`
- **Scopes**: `crm.objects.contacts.read`, `crm.objects.contacts.write`, `crm.objects.companies.read`, `crm.objects.companies.write`, `crm.objects.deals.read`, `crm.objects.deals.write`, `tickets`, `crm.schemas.contacts.read`, `crm.schemas.companies.read`, `crm.schemas.deals.read`
### Private App Access Token
Use a HubSpot Private App access token for authentication
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Access Token | HubSpot Private App access token | Yes | `pat-eu1-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
## Available Actions
### Parameters
Maximum results to return (Default: `10`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"contacts": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Contacts",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetRecentContactsOutput",
"type": "object"
}
```
### Parameters
HubSpot contact ID
Properties to retrieve (None = default property set)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "GetContactByIdOutput",
"type": "object"
}
```
### Parameters
Contact email address
First name
Last name
Phone number
Company
Website URL
Additional properties to set
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "CreateContactOutput",
"type": "object"
}
```
### Parameters
HubSpot contact ID
Properties to update
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "UpdateContactOutput",
"type": "object"
}
```
### Parameters
Search query string
Maximum results to return (Default: `10`)
Properties to retrieve (None = default property set)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"contacts": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Contacts",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "SearchContactsOutput",
"type": "object"
}
```
### Parameters
Maximum results to return (Default: `10`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"companies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Companies",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetRecentCompaniesOutput",
"type": "object"
}
```
### Parameters
HubSpot company ID
Properties to retrieve (None = default property set)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "GetCompanyByIdOutput",
"type": "object"
}
```
### Parameters
Company name
Primary domain
Industry
Phone number
Website URL
Additional properties
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "CreateCompanyOutput",
"type": "object"
}
```
### Parameters
HubSpot company ID
Properties to update
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "UpdateCompanyOutput",
"type": "object"
}
```
### Parameters
HubSpot company ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"activities": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Activities",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetCompanyActivityOutput",
"type": "object"
}
```
### Parameters
Search query string
Maximum results to return (Default: `10`)
Properties to retrieve (None = default property set)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"companies": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Companies",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "SearchCompaniesOutput",
"type": "object"
}
```
### Parameters
Maximum results to return (Default: `10`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"deals": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Deals",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetRecentDealsOutput",
"type": "object"
}
```
### Parameters
HubSpot deal ID
Properties to retrieve (None = default property set)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "GetDealByIdOutput",
"type": "object"
}
```
### Parameters
Deal name
Pipeline ID
Stage ID
Deal amount
Expected close date (ISO 8601)
Additional properties
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "CreateDealOutput",
"type": "object"
}
```
### Parameters
HubSpot deal ID
Properties to update
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "UpdateDealOutput",
"type": "object"
}
```
### Parameters
Search query string
Maximum results to return (Default: `10`)
Properties to retrieve (None = default property set)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"deals": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Deals",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "SearchDealsOutput",
"type": "object"
}
```
### Parameters
Maximum results to return (Default: `10`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"tickets": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Tickets",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetRecentTicketsOutput",
"type": "object"
}
```
### Parameters
HubSpot ticket ID
Properties to retrieve (None = default property set)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "GetTicketByIdOutput",
"type": "object"
}
```
### Parameters
Ticket subject
Ticket content
Pipeline ID
Pipeline stage ID
LOW / MEDIUM / HIGH
Additional properties
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "CreateTicketOutput",
"type": "object"
}
```
### Parameters
HubSpot ticket ID
Properties to update
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "UpdateTicketOutput",
"type": "object"
}
```
### Parameters
Search query string
Maximum results to return (Default: `10`)
Properties to retrieve (None = default property set)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"tickets": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Tickets",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "SearchTicketsOutput",
"type": "object"
}
```
### Parameters
Note body content
Contact IDs to associate
Company IDs to associate
Deal IDs to associate
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "CreateNoteOutput",
"type": "object"
}
```
### Parameters
Task subject
Task body
Due date (ISO 8601)
Priority (NONE/LOW/MEDIUM/HIGH) (Default: `NONE`)
Status (NOT_STARTED/IN_PROGRESS/COMPLETED/etc.) (Default: `NOT_STARTED`)
Contact IDs to associate
Company IDs to associate
Deal IDs to associate
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "CreateTaskOutput",
"type": "object"
}
```
### Parameters
Meeting title
Start time (ISO 8601 or epoch ms)
End time
Meeting body
Contact IDs to associate
Company IDs to associate
Deal IDs to associate
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "CreateMeetingOutput",
"type": "object"
}
```
### Parameters
One of contacts/companies/deals/tickets
Property name to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "GetPropertyOutput",
"type": "object"
}
```
### Parameters
One of contacts/companies/deals/tickets
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"properties": {
"type": "array",
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Properties"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListPropertiesOutput",
"type": "object"
}
```
## Related integrations
## Links
- [HubSpot](https://www.hubspot.com)
---
# Hunter Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/hunter
Find and verify professional email addresses using the Hunter.io API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/hunter/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Hunter** to any ModuleX agent or workflow. Find and verify professional email addresses, search domains for contacts, and manage leads using the Hunter.io API (`api.hunter.io/v2`).
**Categories**: Sales · Marketing & Sales · Lead Generation · Email · **Auth**: API Key · **Actions**: 13
## Authentication
### API Key Authentication
Authenticate using your Hunter API key
Go to https://hunter.io and sign in
Navigate to your account API settings at https://hunter.io/api-keys
Copy your API key
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Hunter API Key | Your Hunter API key from hunter.io/api-keys | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Name"
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Name"
},
"plan_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Plan Name"
},
"plan_level": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Plan Level"
},
"reset_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Reset Date"
},
"team_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Team Id"
},
"calls_used": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Calls Used"
},
"calls_available": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Calls Available"
}
},
"required": [
"success"
],
"title": "AccountInformationOutput",
"type": "object"
}
```
### Parameters
The email address you want to find information about
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CombinedEnrichmentOutput",
"type": "object"
}
```
### Parameters
The email address of the lead
The first name of the lead
The last name of the lead
The job title of the lead
The name of the company the lead is working in
The sector of the company. Allowed values: Animal, Art & Entertainment, Automotive, Beauty & Fitness, Books & Literature, Education & Career, Finance, Food & Drink, Game, Health, Hobby & Leisure, Home & Garden, Industry, Internet & Telecom, Law & Government, Manufacturing, News, Real Estate, Science, Retail, Sport, Technology, Travel
The size of the company the lead is working in
Estimation of the probability the email address returned is correct, between 0 and 100
The domain name of the company
The country of the lead (ISO 3166-1 alpha-2 standard)
The address of the public profile on LinkedIn
The phone number of the lead
The Twitter handle of the lead
Some personal notes about the lead
The source where the lead has been found
The identifier of the list the lead belongs to. If not specified, the lead is saved in the last list created
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Name"
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Name"
}
},
"required": [
"success"
],
"title": "CreateLeadOutput",
"type": "object"
}
```
### Parameters
The unique identifier of the lead
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "DeleteLeadOutput",
"type": "object"
}
```
### Parameters
Domain name from which you want to find the email addresses. For example, 'stripe.com'. Either domain or company must be provided
The company name from which you want to find the email addresses. For example, 'stripe'. Either domain or company must be provided
Specifies the max number of email addresses to return (Default: `100`)
Get only personal or generic email addresses. Allowed values: personal, generic
Get only email addresses for people with the selected seniority level(s). Comma-separated values: junior, senior, executive
Get only email addresses for people working in the selected department(s). Comma-separated values: executive, it, finance, management, sales, legal, support, hr, marketing, communication, education, design, health, operations
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Domain"
},
"disposable": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Disposable"
},
"webmail": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Webmail"
},
"accept_all": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Accept All"
},
"pattern": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Pattern"
},
"organization": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Organization"
},
"emails": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Emails",
"type": "array"
},
"total_results": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Results"
}
},
"required": [
"success"
],
"title": "DomainSearchOutput",
"type": "object"
}
```
### Parameters
Domain name from which you want to find the email addresses. For example, 'stripe.com'. Either domain or company must be provided
The company name from which you want to find the email addresses. For example, 'stripe'. Either domain or company must be provided
Get only personal or generic email addresses. Allowed values: personal, generic
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"personal_emails": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Personal Emails"
},
"generic_emails": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Generic Emails"
},
"department": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Department"
}
},
"required": [
"success"
],
"title": "EmailCountOutput",
"type": "object"
}
```
### Parameters
Domain name from which you want to find the email addresses. For example, 'stripe.com'. Either domain or company must be provided
The company name from which you want to find the email addresses. For example, 'stripe'. Either domain or company must be provided
The person's first name
The person's last name
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Name"
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Name"
},
"score": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Score"
},
"domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Domain"
},
"accept_all": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Accept All"
},
"position": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Position"
},
"twitter": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Twitter"
},
"linkedin_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Linkedin Url"
},
"phone_number": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Phone Number"
},
"company": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company"
},
"sources": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Sources",
"type": "array"
}
},
"required": [
"success"
],
"title": "EmailFinderOutput",
"type": "object"
}
```
### Parameters
The email address you want to verify
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"result": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
},
"score": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Score"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"regexp": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Regexp"
},
"gibberish": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Gibberish"
},
"disposable": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Disposable"
},
"webmail": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Webmail"
},
"mx_records": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Mx Records"
},
"smtp_server": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Smtp Server"
},
"smtp_check": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Smtp Check"
},
"accept_all": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Accept All"
},
"block": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Block"
},
"sources": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Sources",
"type": "array"
}
},
"required": [
"success"
],
"title": "EmailVerifierOutput",
"type": "object"
}
```
### Parameters
The unique identifier of the lead
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Name"
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Name"
},
"position": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Position"
},
"company": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company"
}
},
"required": [
"success"
],
"title": "GetLeadOutput",
"type": "object"
}
```
### Parameters
Identifier of the leads list to retrieve
A limit on the number of leads to be returned. Limit can range between 1 and 100 (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"leads": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Leads",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetLeadsListOutput",
"type": "object"
}
```
### Parameters
Only returns the leads belonging to this list
Filter leads by email
Filter leads by first name
Filter leads by last name
Filter leads by position
Filter leads by company
Filter leads by industry
Filter leads by website
Filter leads by country code (ISO 3166-1 alpha-2)
Filter leads by company size
Filter leads by source
Filter leads by Twitter handle
Filter leads by LinkedIn URL
Filter leads by phone number
Filter by synchronization status. Allowed values: pending, error, success
Filter by sending status. Comma-separated values: clicked, opened, sent, pending, error, bounced, unsubscribed, replied
Filter by verification status. Comma-separated values: accept_all, disposable, invalid, unknown, valid, webmail, pending
Filter by last activity. Allowed values: * (any), ~ (unset)
Filter by last contact date. Allowed values: * (any), ~ (unset)
Only returns leads with First Name, Last Name, or Email matching the query
A limit on the number of leads to be returned. Limit can range between 1 and 1000 (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"leads": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Leads",
"type": "array"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
}
},
"required": [
"success"
],
"title": "ListLeadsOutput",
"type": "object"
}
```
### Parameters
A limit on the number of lists to be returned. Limit can range between 1 and 100 (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"leads_lists": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Leads Lists",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListLeadsListsOutput",
"type": "object"
}
```
### Parameters
The unique identifier of the lead
The email address of the lead
The person's first name
The person's last name
The person's position in the company
The company name
The website URL of the company
The person's phone number
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "UpdateLeadOutput",
"type": "object"
}
```
## Limits & Quotas
- **Free plan**: 25 searches and 50 verifications per month.
- **Paid plans**: Limits scale with plan tier (up to 30,000+ requests/month on Enterprise).
- **Rate limit**: 10 requests/second across all endpoints.
- **Error model**: Non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Hunter](https://hunter.io)
---
# Icypeas Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/icypeas
Find a professional email address from a name and company domain, or verify whether an existing email is valid and deliverable. Results are returned asynchronously via polling.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/icypeas/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Icypeas** to any ModuleX agent or workflow. Find and verify professional email addresses against the Icypeas REST API (`app.icypeas.com`). Resolve a likely professional email from a person's name and company domain, or check whether an existing address is valid and deliverable. Both operations run asynchronously: a job is submitted, then the result is fetched by polling.
**Categories**: Sales · Enrichment · Sales Engagement · **Auth**: API Key · **Actions**: 2
## Authentication
### API Key Authentication
Authenticate using your Icypeas API key
Go to https://app.icypeas.com and sign up or log in
Open the API settings / API access section in your account
Create a new API key or copy your existing one
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Icypeas API Key | Your Icypeas API key from app.icypeas.com | Yes | `-` |
## Available Actions
### Parameters
Target company domain (e.g. stripe.com) or company name (e.g. Stripe)
Target person's first name
Target person's last name
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"search_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Search Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"firstname": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Firstname"
},
"lastname": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lastname"
},
"item": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Item"
}
},
"required": [
"success"
],
"title": "FindEmailOutput",
"type": "object"
}
```
### Parameters
Email address to verify (e.g. john@stripe.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"search_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Search Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"valid": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Valid"
},
"item": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Item"
}
},
"required": [
"success"
],
"title": "VerifyEmailOutput",
"type": "object"
}
```
## Limits & Quotas
- **Async polling**: each call submits a job, then polls the read
endpoint roughly every 3 seconds for up to 120 seconds. If the job
does not reach a terminal status in that window, the call returns
`success=False` with an explanatory error.
- **Terminal statuses**: `FOUND`, `DEBITED`, `NOT_FOUND`,
`DEBITED_NOT_FOUND`, `BAD_INPUT`, `INSUFFICIENT_FUNDS`, `ABORTED`. A
clean no-match (`NOT_FOUND`) is still a successful run — `email` is
simply `null` and, for verification, `valid` is `false`.
- **Rate limits**: approximately 60 requests/minute.
- **Pricing** (approx., per vendor pricing page): email finding ~1
credit per found email; email verification ~0.1 credit per check.
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising. Plan for
retries on the agent side based on the error string.
## Related integrations
## Links
- [Icypeas](https://www.icypeas.com)
---
# incident.io Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/incidentio
Manage incidents, actions, follow-ups, workflows, schedules, escalations, custom fields, and more with incident.io — the incident management and on-call response platform.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/incidentio/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **incident.io** to any ModuleX agent or workflow. Incident management and on-call response against the incident.io REST API (`api.incident.io`). Manage incidents, actions, follow-ups, workflows, schedules, escalations, escalation paths, custom fields, incident roles, and reference data.
**Categories**: Monitoring & Observability · Incident Management · On Call · **Auth**: API Key · **Actions**: 46
## Authentication
### API Key Authentication
Authenticate using your incident.io API key
Log in to your incident.io dashboard
Go to Settings -> API keys
Create a new API key and select the permissions it should have
Copy the key (it is shown only once) and paste it below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| incident.io API Key | Your incident.io API key from Settings -> API keys | Yes | `-` |
## Available Actions
### Parameters
Number of results to return per page (e.g., 10, 25, 50)
Pagination cursor to fetch the next page of results
Sort order: 'created_at_newest_first' or 'created_at_oldest_first'
How to combine filters: 'all' or 'any'
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"incidents": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Incidents",
"type": "array"
},
"pagination_meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Pagination Meta"
}
},
"required": [
"success"
],
"title": "IncidentsListOutput",
"type": "object"
}
```
### Parameters
Unique identifier to prevent duplicate creation (e.g., a UUID)
ID of the severity level
Visibility of the incident: 'public' or 'private'
Name of the incident
Brief summary of the incident
ID of the incident type
ID of the initial incident status
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"incident": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Incident"
}
},
"required": [
"success"
],
"title": "IncidentsCreateOutput",
"type": "object"
}
```
### Parameters
ID of the incident to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"incident": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Incident"
}
},
"required": [
"success"
],
"title": "IncidentsShowOutput",
"type": "object"
}
```
### Parameters
ID of the incident to update
Whether to notify the incident channel about this update
Updated name of the incident
Updated summary of the incident
Updated severity ID
Updated status ID
Updated incident type ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"incident": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Incident"
}
},
"required": [
"success"
],
"title": "IncidentsUpdateOutput",
"type": "object"
}
```
### Parameters
Filter actions by incident ID
Filter by incident mode: standard, retrospective, test, tutorial, or stream
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"actions": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Actions",
"type": "array"
}
},
"required": [
"success"
],
"title": "ActionsListOutput",
"type": "object"
}
```
### Parameters
Action ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"action": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Action"
}
},
"required": [
"success"
],
"title": "ActionsShowOutput",
"type": "object"
}
```
### Parameters
Filter follow-ups by incident ID
Filter by incident mode: standard, retrospective, test, tutorial, or stream
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"follow_ups": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Follow Ups",
"type": "array"
}
},
"required": [
"success"
],
"title": "FollowUpsListOutput",
"type": "object"
}
```
### Parameters
Follow-up ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"follow_up": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Follow Up"
}
},
"required": [
"success"
],
"title": "FollowUpsShowOutput",
"type": "object"
}
```
### Parameters
Number of results to return per page (e.g., 10, 25, 50)
Pagination cursor to fetch the next page of results
Filter users by email address
Filter users by Slack user ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"users": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Users",
"type": "array"
},
"pagination_meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Pagination Meta"
}
},
"required": [
"success"
],
"title": "UsersListOutput",
"type": "object"
}
```
### Parameters
The unique identifier of the user to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"user": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "User"
}
},
"required": [
"success"
],
"title": "UsersShowOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"workflows": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Workflows",
"type": "array"
}
},
"required": [
"success"
],
"title": "WorkflowsListOutput",
"type": "object"
}
```
### Parameters
Name of the workflow
Folder to organize the workflow in
State of the workflow: active, draft, or disabled (Default: `draft`)
Trigger type for the workflow (Default: `incident.updated`)
Array of workflow steps (defaults to [])
Array of condition groups controlling when the workflow runs
When to run: newly_created, newly_created_and_active, active, or all (Default: `newly_created`)
Array of incident modes to run on (defaults to ['standard'])
Whether to include private incidents (Default: `true`)
Whether to continue executing subsequent steps if one fails (Default: `false`)
Array of fields making the workflow run once per combination
Array of workflow expressions for advanced logic
Delay configuration object
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"workflow": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Workflow"
},
"management_meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Management Meta"
}
},
"required": [
"success"
],
"title": "WorkflowsCreateOutput",
"type": "object"
}
```
### Parameters
The ID of the workflow to retrieve
Skip workflow step upgrades when existing step parameters changed
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"workflow": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Workflow"
},
"management_meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Management Meta"
}
},
"required": [
"success"
],
"title": "WorkflowsShowOutput",
"type": "object"
}
```
### Parameters
The ID of the workflow to update
New name for the workflow
Complete array of workflow steps
Complete array of workflow condition groups
When to run: newly_created, newly_created_and_active, active, or all
Complete array of incident modes to run on
Whether to include private incidents
Whether to continue executing subsequent steps if one fails
Complete array of fields that make the workflow run once
Complete array of workflow expressions
New state: active, draft, or disabled
New folder for the workflow
Delay configuration object
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"workflow": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Workflow"
},
"management_meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Management Meta"
}
},
"required": [
"success"
],
"title": "WorkflowsUpdateOutput",
"type": "object"
}
```
### Parameters
The ID of the workflow to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "WorkflowsDeleteOutput",
"type": "object"
}
```
### Parameters
Number of results to return per page (e.g., 10, 25, 50)
Pagination cursor to fetch the next page of results
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"schedules": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Schedules",
"type": "array"
},
"pagination_meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Pagination Meta"
}
},
"required": [
"success"
],
"title": "SchedulesListOutput",
"type": "object"
}
```
### Parameters
Name of the schedule
Timezone for the schedule (e.g., America/New_York)
Schedule configuration object with rotations
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"schedule": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Schedule"
}
},
"required": [
"success"
],
"title": "SchedulesCreateOutput",
"type": "object"
}
```
### Parameters
The ID of the schedule
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"schedule": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Schedule"
}
},
"required": [
"success"
],
"title": "SchedulesShowOutput",
"type": "object"
}
```
### Parameters
The ID of the schedule to update
New name for the schedule
New timezone for the schedule
Schedule configuration object with rotations
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"schedule": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Schedule"
}
},
"required": [
"success"
],
"title": "SchedulesUpdateOutput",
"type": "object"
}
```
### Parameters
The ID of the schedule to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "SchedulesDeleteOutput",
"type": "object"
}
```
### Parameters
Number of results to return per page (e.g., 10, 25, 50)
Pagination cursor to fetch the next page of results
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"escalations": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Escalations",
"type": "array"
},
"pagination_meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Pagination Meta"
}
},
"required": [
"success"
],
"title": "EscalationsListOutput",
"type": "object"
}
```
### Parameters
Unique identifier to prevent duplicate escalation creation
Title of the escalation
ID of the escalation path (required if user_ids not provided)
Comma-separated user IDs to notify (required if no escalation_path_id)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"escalation": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Escalation"
}
},
"required": [
"success"
],
"title": "EscalationsCreateOutput",
"type": "object"
}
```
### Parameters
The ID of the escalation policy
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"escalation": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Escalation"
}
},
"required": [
"success"
],
"title": "EscalationsShowOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"custom_fields": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Custom Fields",
"type": "array"
}
},
"required": [
"success"
],
"title": "CustomFieldsListOutput",
"type": "object"
}
```
### Parameters
Name of the custom field
Description of the custom field
Field type: text, single_select, multi_select, numeric, link, etc.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"custom_field": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Custom Field"
}
},
"required": [
"success"
],
"title": "CustomFieldsCreateOutput",
"type": "object"
}
```
### Parameters
Custom field ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"custom_field": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Custom Field"
}
},
"required": [
"success"
],
"title": "CustomFieldsShowOutput",
"type": "object"
}
```
### Parameters
Custom field ID
New name for the custom field
New description for the custom field
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"custom_field": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Custom Field"
}
},
"required": [
"success"
],
"title": "CustomFieldsUpdateOutput",
"type": "object"
}
```
### Parameters
Custom field ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "CustomFieldsDeleteOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"severities": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Severities",
"type": "array"
}
},
"required": [
"success"
],
"title": "SeveritiesListOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"incident_statuses": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Incident Statuses",
"type": "array"
}
},
"required": [
"success"
],
"title": "IncidentStatusesListOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"incident_types": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Incident Types",
"type": "array"
}
},
"required": [
"success"
],
"title": "IncidentTypesListOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"incident_roles": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Incident Roles",
"type": "array"
}
},
"required": [
"success"
],
"title": "IncidentRolesListOutput",
"type": "object"
}
```
### Parameters
Name of the incident role
Description of the incident role
Instructions for the incident role
Short form abbreviation for the role
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"incident_role": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Incident Role"
}
},
"required": [
"success"
],
"title": "IncidentRolesCreateOutput",
"type": "object"
}
```
### Parameters
The ID of the incident role
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"incident_role": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Incident Role"
}
},
"required": [
"success"
],
"title": "IncidentRolesShowOutput",
"type": "object"
}
```
### Parameters
The ID of the incident role to update
Name of the incident role
Description of the incident role
Instructions for the incident role
Short form abbreviation for the role
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"incident_role": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Incident Role"
}
},
"required": [
"success"
],
"title": "IncidentRolesUpdateOutput",
"type": "object"
}
```
### Parameters
The ID of the incident role to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "IncidentRolesDeleteOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"incident_timestamps": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Incident Timestamps",
"type": "array"
}
},
"required": [
"success"
],
"title": "IncidentTimestampsListOutput",
"type": "object"
}
```
### Parameters
The ID of the incident timestamp
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"incident_timestamp": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Incident Timestamp"
}
},
"required": [
"success"
],
"title": "IncidentTimestampsShowOutput",
"type": "object"
}
```
### Parameters
The ID of the incident to get updates for
Number of results to return per page (e.g., 10, 25, 50)
Pagination cursor to fetch the next page of results
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"incident_updates": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Incident Updates",
"type": "array"
},
"pagination_meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Pagination Meta"
}
},
"required": [
"success"
],
"title": "IncidentUpdatesListOutput",
"type": "object"
}
```
### Parameters
The ID of the schedule to get entries for
Start of the filter window in ISO 8601 format
End of the filter window in ISO 8601 format
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"schedule_entries": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Schedule Entries"
},
"pagination_meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Pagination Meta"
}
},
"required": [
"success"
],
"title": "ScheduleEntriesListOutput",
"type": "object"
}
```
### Parameters
The ID of the rotation to override
The ID of the layer this override applies to
The ID of the schedule
When the override starts in ISO 8601 format
When the override ends in ISO 8601 format
The ID of the user to assign
The email of the user to assign
The Slack ID of the user to assign
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"override": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Override"
}
},
"required": [
"success"
],
"title": "ScheduleOverridesCreateOutput",
"type": "object"
}
```
### Parameters
Number of results to return per page (e.g., 10, 25, 50)
Pagination cursor to fetch the next page of results
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"escalation_paths": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Escalation Paths",
"type": "array"
},
"pagination_meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Pagination Meta"
}
},
"required": [
"success"
],
"title": "EscalationPathsListOutput",
"type": "object"
}
```
### Parameters
Name of the escalation path
Array of escalation levels. Each level has targets (array of {id, type, schedule_id?, user_id?, urgency}) and time_to_ack_seconds
Optional working hours config: array of {weekday, start_time, end_time}
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"escalation_path": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Escalation Path"
}
},
"required": [
"success"
],
"title": "EscalationPathsCreateOutput",
"type": "object"
}
```
### Parameters
The ID of the escalation path
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"escalation_path": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Escalation Path"
}
},
"required": [
"success"
],
"title": "EscalationPathsShowOutput",
"type": "object"
}
```
### Parameters
The ID of the escalation path to update
New name for the escalation path
New escalation path: array of levels with targets and time_to_ack_seconds
New working hours config: array of {weekday, start_time, end_time}
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"escalation_path": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Escalation Path"
}
},
"required": [
"success"
],
"title": "EscalationPathsUpdateOutput",
"type": "object"
}
```
### Parameters
The ID of the escalation path to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "EscalationPathsDeleteOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limit**: 1200 requests/minute per API key (default).
- **Endpoints**: most resources live under `/v2`; severities, incident
statuses, and incident types are served under `/v1`.
- **Pagination**: list endpoints accept `page_size` plus an `after`
cursor; the tools expose both as optional parameters and do not
auto-loop — pass the returned cursor to fetch the next page.
- **Error model**: non-2xx responses and timeouts are caught and returned
as `success=False` + `error` rather than raising. Plan retries on the
agent side based on the error string.
## Related integrations
## Links
- [incident.io](https://incident.io)
---
# Insightly Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/insightly
CRM and project management platform for managing contacts, tasks, and sales pipelines
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/insightly/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Insightly** to any ModuleX agent or workflow. CRM and project management platform for managing contacts, tasks, and sales pipelines via the Insightly REST API (`api.{pod}.insightly.com/v3.1`).
**Categories**: CRM · Sales · Productivity & Collaboration · **Auth**: Insightly API Key · **Actions**: 2
## Authentication
### Insightly API Key
Authenticate using your Insightly API key and pod identifier
Log in to your Insightly account
Go to User Settings > API
Copy your API key
Find your pod identifier from your Insightly URL (e.g. na1, au1)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Pod | Your Insightly pod/region identifier (e.g. na1, au1) found in your Insightly URL | Yes | `na1` |
| API Key | Your Insightly API key from User Settings > API | Yes | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
## Available Actions
### Parameters
The first name of the contact
The last name of the contact
The email address of the contact
The title of the contact
The phone number of the contact
The street address of the contact
The city of the contact
The state of the contact
The zip code/postcode of the contact
The country of the contact
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"contact_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Contact Id"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Name"
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Name"
},
"email_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Address"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Phone"
}
},
"required": [
"success"
],
"title": "CreateContactOutput",
"type": "object"
}
```
### Parameters
The title of the task
The status of the task. Allowed values: Not Started, In Progress, Completed, Deferred, Waiting
The due date of the task in YYYY-MM-DD format (e.g. 2023-08-20)
Identifier of a task category
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"task_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Task Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"due_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Due Date"
},
"category_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Category Id"
}
},
"required": [
"success"
],
"title": "CreateTaskOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limits**: Insightly enforces per-plan rate limits (typically 10 requests/second for Professional plans, higher for Enterprise).
- **Pricing**: API access requires a paid Insightly plan (Professional or higher).
- **Error model**: non-2xx responses are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Insightly](https://www.insightly.com)
---
# Instacart Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/instacart
Create shareable recipe pages, shopping lists, and find nearby retailers on Instacart. No authentication required.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/instacart/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Instacart** to any ModuleX agent or workflow. Public Instacart actions: build shareable recipe + shopping-list pages and look up retailers by postal code. No API key required.
**Categories**: E-Commerce · Business Services · Grocery · Retail · Shopping · **Auth**: ModuleX Managed · **Actions**: 3
## Authentication
### ModuleX Managed
This integration uses Instacart's public APIs. No API key is required for requests.
## Available Actions
### Parameters
The title of the recipe
List of ingredients for the recipe
Recipe instructions/directions
Number of servings
URL to recipe image
Original recipe source URL
Partner ID for affiliate tracking
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"shareable_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Shareable Url"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"ingredient_count": {
"default": 0,
"title": "Ingredient Count",
"type": "integer"
},
"ingredients": {
"items": {
"type": "string"
},
"title": "Ingredients",
"type": "array"
}
},
"required": [
"success"
],
"title": "CreateRecipePageOutput",
"type": "object"
}
```
### Parameters
The title of the shopping list
List of items to add to the shopping list
Partner ID for affiliate tracking
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"shareable_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Shareable Url"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"item_count": {
"default": 0,
"title": "Item Count",
"type": "integer"
},
"items": {
"items": {
"type": "string"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "CreateShoppingListPageOutput",
"type": "object"
}
```
### Parameters
Postal/ZIP code to search near
Country code (e.g., 'US', 'CA') (Default: `US`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"postal_code": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Postal Code"
},
"country_code": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Country Code"
},
"retailer_count": {
"default": 0,
"title": "Retailer Count",
"type": "integer"
},
"retailers": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Retailers",
"type": "array"
},
"store_finder_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Store Finder Url"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "GetNearbyRetailersOutput",
"type": "object"
}
```
## Limits & Quotas
- Recipe/list pages are pure URL builders (no API hit).
- Retailer lookup goes to Instacart's public `/v3/retailers` endpoint;
on timeout or non-200 the tool returns a store-finder URL as a
usable fallback (still `success=True`).
- Country supported: `US`, `CA`.
## Related integrations
## Links
- [Instacart](https://www.instacart.com)
---
# Instantly Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/instantly
Integrate the Instantly V2 cold-email outreach API. Create and list leads, manage lead interest status, delete leads in bulk, list and create campaigns, reply to emails, and manage lead lists.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/instantly/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Instantly** to any ModuleX agent or workflow. Cold-email outreach automation against the Instantly V2 REST API (`api.instantly.ai`). Manage leads, lead lists, campaigns, and Unibox emails.
**Categories**: Marketing & Advertising · Email · Sales Engagement · **Auth**: API Key · **Actions**: 13
## Authentication
### API Key Authentication
Authenticate using your Instantly V2 API key
Sign in at https://app.instantly.ai
Open Settings and navigate to the 'API Keys' (Integrations) section
Create a new V2 API key with the required scopes
Copy the key and paste it below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Instantly API Key | Your Instantly V2 API key with the required scopes | Yes | `-` |
## Available Actions
### Parameters
Search by first name, last name, or email
Lead filter value, such as FILTER_VAL_CONTACTED or FILTER_VAL_ACTIVE
Campaign ID to filter leads
Lead list ID to filter leads
Whether the lead is in a campaign
Whether the lead is in a list
Lead IDs to include
Lead IDs to exclude
Lead email addresses to include
Organization user IDs to filter leads
Smart view ID to filter leads
Whether the lead is a website visitor
Whether to return distinct contacts
Enrichment status filter
Email security gateway code filter
Number of leads to return, from 1 to 100
Forward pagination cursor from next_starting_after
### Response
```json
{
"$defs": {
"LeadDetail": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"timestamp_created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Created"
},
"timestamp_updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Updated"
},
"organization": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Organization"
},
"campaign": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Campaign"
},
"status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"personalization": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Personalization"
},
"website": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Website"
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Name"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Name"
},
"company_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Name"
},
"job_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Job Title"
},
"phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Phone"
},
"email_open_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Open Count"
},
"email_reply_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Reply Count"
},
"email_click_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Click Count"
},
"company_domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Domain"
},
"payload": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Payload"
},
"lt_interest_status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Lt Interest Status"
}
},
"title": "LeadDetail",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"leads": {
"items": {
"$ref": "#/$defs/LeadDetail"
},
"title": "Leads",
"type": "array"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"next_starting_after": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Starting After"
}
},
"required": [
"success"
],
"title": "ListLeadsOutput",
"type": "object"
}
```
### Parameters
Lead ID
### Response
```json
{
"$defs": {
"LeadDetail": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"timestamp_created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Created"
},
"timestamp_updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Updated"
},
"organization": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Organization"
},
"campaign": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Campaign"
},
"status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"personalization": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Personalization"
},
"website": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Website"
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Name"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Name"
},
"company_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Name"
},
"job_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Job Title"
},
"phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Phone"
},
"email_open_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Open Count"
},
"email_reply_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Reply Count"
},
"email_click_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Click Count"
},
"company_domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Domain"
},
"payload": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Payload"
},
"lt_interest_status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Lt Interest Status"
}
},
"title": "LeadDetail",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"lead": {
"anyOf": [
{
"$ref": "#/$defs/LeadDetail"
},
{
"type": "null"
}
],
"default": null
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"email_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Address"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Name"
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Name"
},
"campaign": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Campaign"
},
"status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
}
},
"required": [
"success"
],
"title": "GetLeadOutput",
"type": "object"
}
```
### Parameters
Campaign ID associated with the lead
Lead list ID associated with the lead
Lead email address. Required when adding to a campaign.
Lead first name
Lead last name
Lead company name
Lead job title
Lead phone number
Lead website
Lead personalization text
Lead interest status value
Potential value of the lead
Organization user ID assigned to the lead
Skip if the lead already exists in the workspace
Skip if the lead already exists in the campaign
Skip if the lead already exists in the list
Blocklist ID to check for the lead
Whether to verify leads imported from Lead Finder
Whether to verify leads on import
Custom variable object with string, number, boolean, or null values
### Response
```json
{
"$defs": {
"LeadDetail": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"timestamp_created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Created"
},
"timestamp_updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Updated"
},
"organization": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Organization"
},
"campaign": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Campaign"
},
"status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"personalization": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Personalization"
},
"website": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Website"
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Name"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Name"
},
"company_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Name"
},
"job_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Job Title"
},
"phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Phone"
},
"email_open_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Open Count"
},
"email_reply_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Reply Count"
},
"email_click_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Click Count"
},
"company_domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Domain"
},
"payload": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Payload"
},
"lt_interest_status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Lt Interest Status"
}
},
"title": "LeadDetail",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"lead": {
"anyOf": [
{
"$ref": "#/$defs/LeadDetail"
},
{
"type": "null"
}
],
"default": null
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"email_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Address"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Name"
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Name"
},
"campaign": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Campaign"
},
"status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
}
},
"required": [
"success"
],
"title": "CreateLeadOutput",
"type": "object"
}
```
### Parameters
Campaign ID to delete leads from. Required if list_id is not provided.
Lead list ID to delete leads from. Required if campaign_id is not provided.
Optional lead status filter
Specific lead IDs to delete
Maximum number of matching leads to delete, up to 10000
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
}
},
"required": [
"success"
],
"title": "DeleteLeadsOutput",
"type": "object"
}
```
### Parameters
Lead email address
Interest status value. Pass null to reset to Lead.
Campaign ID for the lead
Lead list ID for the lead
AI interest value to set for the lead
Whether to disable auto interest
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "UpdateLeadInterestStatusOutput",
"type": "object"
}
```
### Parameters
Number of campaigns to return, from 1 to 100
Pagination cursor from next_starting_after
Search by campaign name
Comma-separated campaign tag IDs
AI Sales Agent ID filter
Campaign status enum value
### Response
```json
{
"$defs": {
"CampaignDetail": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"pl_value": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Pl Value"
},
"status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"is_evergreen": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Evergreen"
},
"timestamp_created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Created"
},
"timestamp_updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Updated"
},
"email_gap": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Gap"
},
"daily_limit": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Daily Limit"
},
"daily_max_leads": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Daily Max Leads"
},
"open_tracking": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Open Tracking"
},
"stop_on_reply": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Stop On Reply"
},
"sequences": {
"items": {},
"title": "Sequences",
"type": "array"
},
"campaign_schedule": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Campaign Schedule"
}
},
"title": "CampaignDetail",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"campaigns": {
"items": {
"$ref": "#/$defs/CampaignDetail"
},
"title": "Campaigns",
"type": "array"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"next_starting_after": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Starting After"
}
},
"required": [
"success"
],
"title": "ListCampaignsOutput",
"type": "object"
}
```
### Parameters
Campaign name
Campaign schedule object with schedules array
Campaign sequence definitions
Sending email accounts
Daily sending limit
Daily maximum new leads to contact
Whether to track opens
Whether to stop the campaign on reply
Whether to track links
Whether the campaign is text only
Gap between emails in minutes
Value of every positive lead
### Response
```json
{
"$defs": {
"CampaignDetail": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"pl_value": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Pl Value"
},
"status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"is_evergreen": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Evergreen"
},
"timestamp_created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Created"
},
"timestamp_updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Updated"
},
"email_gap": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Gap"
},
"daily_limit": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Daily Limit"
},
"daily_max_leads": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Daily Max Leads"
},
"open_tracking": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Open Tracking"
},
"stop_on_reply": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Stop On Reply"
},
"sequences": {
"items": {},
"title": "Sequences",
"type": "array"
},
"campaign_schedule": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Campaign Schedule"
}
},
"title": "CampaignDetail",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"campaign": {
"anyOf": [
{
"$ref": "#/$defs/CampaignDetail"
},
{
"type": "null"
}
],
"default": null
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
}
},
"required": [
"success"
],
"title": "CreateCampaignOutput",
"type": "object"
}
```
### Parameters
Campaign ID
Campaign name
Campaign schedule object with schedules array
Campaign sequence definitions
Sending email accounts
Daily sending limit
Daily maximum new leads to contact
Whether to track opens
Whether to stop the campaign on reply
Whether to track links
Whether the campaign is text only
Gap between emails in minutes
Value of every positive lead
### Response
```json
{
"$defs": {
"CampaignDetail": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"pl_value": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Pl Value"
},
"status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"is_evergreen": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Evergreen"
},
"timestamp_created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Created"
},
"timestamp_updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Updated"
},
"email_gap": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Gap"
},
"daily_limit": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Daily Limit"
},
"daily_max_leads": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Daily Max Leads"
},
"open_tracking": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Open Tracking"
},
"stop_on_reply": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Stop On Reply"
},
"sequences": {
"items": {},
"title": "Sequences",
"type": "array"
},
"campaign_schedule": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Campaign Schedule"
}
},
"title": "CampaignDetail",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"campaign": {
"anyOf": [
{
"$ref": "#/$defs/CampaignDetail"
},
{
"type": "null"
}
],
"default": null
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
}
},
"required": [
"success"
],
"title": "PatchCampaignOutput",
"type": "object"
}
```
### Parameters
Campaign ID
### Response
```json
{
"$defs": {
"CampaignDetail": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"pl_value": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Pl Value"
},
"status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"is_evergreen": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Evergreen"
},
"timestamp_created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Created"
},
"timestamp_updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Updated"
},
"email_gap": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Gap"
},
"daily_limit": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Daily Limit"
},
"daily_max_leads": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Daily Max Leads"
},
"open_tracking": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Open Tracking"
},
"stop_on_reply": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Stop On Reply"
},
"sequences": {
"items": {},
"title": "Sequences",
"type": "array"
},
"campaign_schedule": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Campaign Schedule"
}
},
"title": "CampaignDetail",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"campaign": {
"anyOf": [
{
"$ref": "#/$defs/CampaignDetail"
},
{
"type": "null"
}
],
"default": null
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
}
},
"required": [
"success"
],
"title": "ActivateCampaignOutput",
"type": "object"
}
```
### Parameters
Number of emails to return, from 1 to 100
Pagination cursor from next_starting_after
Search query, email address, or thread:<thread-id>
Campaign ID filter
Lead list ID filter
Email interest status filter
Sending email account filter
Lead email address filter
Unread status filter
### Response
```json
{
"$defs": {
"EmailBody": {
"additionalProperties": false,
"properties": {
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
},
"html": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Html"
}
},
"title": "EmailBody",
"type": "object"
},
"EmailDetail": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"timestamp_created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Created"
},
"timestamp_email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Email"
},
"message_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message Id"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"from_address_email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "From Address Email"
},
"to_address_email_list": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "To Address Email List"
},
"cc_address_email_list": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cc Address Email List"
},
"bcc_address_email_list": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Bcc Address Email List"
},
"reply_to": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Reply To"
},
"body": {
"anyOf": [
{
"$ref": "#/$defs/EmailBody"
},
{
"type": "null"
}
],
"default": null
},
"organization_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Organization Id"
},
"campaign_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Campaign Id"
},
"subsequence_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subsequence Id"
},
"list_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "List Id"
},
"lead": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lead"
},
"lead_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lead Id"
},
"eaccount": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Eaccount"
},
"ue_type": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Ue Type"
},
"is_unread": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Unread"
},
"is_auto_reply": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Auto Reply"
},
"i_status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "I Status"
},
"thread_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Thread Id"
},
"content_preview": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Preview"
}
},
"title": "EmailDetail",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"emails": {
"items": {
"$ref": "#/$defs/EmailDetail"
},
"title": "Emails",
"type": "array"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"next_starting_after": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Starting After"
}
},
"required": [
"success"
],
"title": "ListEmailsOutput",
"type": "object"
}
```
### Parameters
Connected email account used to send the reply
Email ID to reply to
Reply subject
Reply body as plain text
Reply body as HTML
Comma-separated CC email addresses
Comma-separated BCC email addresses
### Response
```json
{
"$defs": {
"EmailBody": {
"additionalProperties": false,
"properties": {
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
},
"html": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Html"
}
},
"title": "EmailBody",
"type": "object"
},
"EmailDetail": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"timestamp_created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Created"
},
"timestamp_email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Email"
},
"message_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message Id"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"from_address_email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "From Address Email"
},
"to_address_email_list": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "To Address Email List"
},
"cc_address_email_list": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cc Address Email List"
},
"bcc_address_email_list": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Bcc Address Email List"
},
"reply_to": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Reply To"
},
"body": {
"anyOf": [
{
"$ref": "#/$defs/EmailBody"
},
{
"type": "null"
}
],
"default": null
},
"organization_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Organization Id"
},
"campaign_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Campaign Id"
},
"subsequence_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subsequence Id"
},
"list_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "List Id"
},
"lead": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lead"
},
"lead_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lead Id"
},
"eaccount": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Eaccount"
},
"ue_type": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Ue Type"
},
"is_unread": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Unread"
},
"is_auto_reply": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Auto Reply"
},
"i_status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "I Status"
},
"thread_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Thread Id"
},
"content_preview": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Preview"
}
},
"title": "EmailDetail",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"email": {
"anyOf": [
{
"$ref": "#/$defs/EmailDetail"
},
{
"type": "null"
}
],
"default": null
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"thread_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Thread Id"
}
},
"required": [
"success"
],
"title": "ReplyToEmailOutput",
"type": "object"
}
```
### Parameters
Number of lead lists to return, from 1 to 100
Starting-after cursor from next_starting_after
Filter by enrichment task setting
Search query to filter lead lists by name
### Response
```json
{
"$defs": {
"LeadListDetail": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"organization_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Organization Id"
},
"has_enrichment_task": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has Enrichment Task"
},
"owned_by": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Owned By"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"timestamp_created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Created"
}
},
"title": "LeadListDetail",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"lead_lists": {
"items": {
"$ref": "#/$defs/LeadListDetail"
},
"title": "Lead Lists",
"type": "array"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"next_starting_after": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Starting After"
}
},
"required": [
"success"
],
"title": "ListLeadListsOutput",
"type": "object"
}
```
### Parameters
Lead list name
Whether this list runs enrichment for every added lead
User ID of the lead list owner
### Response
```json
{
"$defs": {
"LeadListDetail": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"organization_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Organization Id"
},
"has_enrichment_task": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has Enrichment Task"
},
"owned_by": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Owned By"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"timestamp_created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Created"
}
},
"title": "LeadListDetail",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"lead_list": {
"anyOf": [
{
"$ref": "#/$defs/LeadListDetail"
},
{
"type": "null"
}
],
"default": null
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
}
},
"required": [
"success"
],
"title": "CreateLeadListOutput",
"type": "object"
}
```
## Limits & Quotas
- List endpoints accept `limit` (1–100) and forward-paginate via the
`next_starting_after` cursor returned in each response — pass it back
as `starting_after` for the next page.
- `update_lead_interest_status` submits an asynchronous background job;
the response carries a submission `message`, not the updated lead.
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising. Plan agent
retries based on the error string.
## Related integrations
## Links
- [Instantly](https://instantly.ai)
---
# Instructure Canvas LMS Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/instructure-canvas
Learning management system for course, assignment, and user management via the Canvas REST API.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/instructure_canvas/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Instructure Canvas LMS** to any ModuleX agent or workflow. Learning management system integration for [Instructure Canvas](https://www.instructure.com/canvas) — course, assignment, and user management via the Canvas REST API (`https://{your-domain}/api/v1`).
**Categories**: Education · Learning Management · **Auth**: Canvas OAuth Token + Domain · **Actions**: 5
## Authentication
### Canvas OAuth Token + Domain
Authenticate using a Canvas access token and your instance domain. Canvas LMS is self-hosted, so both the domain and token are required.
Log into your Canvas instance.
Go to Account > Settings > Approved Integrations (or generate a new access token).
Copy your access token and note your Canvas domain (e.g. myschool.instructure.com).
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Canvas Domain | Your Canvas instance domain (e.g. myschool.instructure.com) | Yes | `myschool.instructure.com` |
| Access Token | Your Canvas API access token | Yes | `7~xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Response
```json
{
"$defs": {
"AccountOption": {
"additionalProperties": false,
"description": "A Canvas account option.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
}
},
"title": "AccountOption",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"accounts": {
"items": {
"$ref": "#/$defs/AccountOption"
},
"title": "Accounts",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListAccountsOutput",
"type": "object"
}
```
### Parameters
The ID of the user whose assignments to list.
The ID of the course to list assignments from.
### Response
```json
{
"$defs": {
"AssignmentSummary": {
"additionalProperties": false,
"description": "A Canvas assignment.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"due_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Due At"
},
"points_possible": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Points Possible"
},
"grading_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Grading Type"
},
"submission_types": {
"items": {
"type": "string"
},
"title": "Submission Types",
"type": "array"
},
"course_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Course Id"
},
"allowed_attempts": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Allowed Attempts"
},
"omit_from_final_grade": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Omit From Final Grade"
}
},
"title": "AssignmentSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"assignments": {
"items": {
"$ref": "#/$defs/AssignmentSummary"
},
"title": "Assignments",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListAssignmentsOutput",
"type": "object"
}
```
### Parameters
The ID of the user whose courses to list.
### Response
```json
{
"$defs": {
"CourseSummary": {
"additionalProperties": false,
"description": "A Canvas course.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"course_code": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Course Code"
},
"workflow_state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Workflow State"
},
"enrollment_term_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Enrollment Term Id"
}
},
"title": "CourseSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"courses": {
"items": {
"$ref": "#/$defs/CourseSummary"
},
"title": "Courses",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListCoursesOutput",
"type": "object"
}
```
### Parameters
The ID of the course to search within.
The search query string.
### Response
```json
{
"$defs": {
"SearchResultItem": {
"additionalProperties": false,
"description": "A search result from Canvas smart search.",
"properties": {
"content_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Id"
},
"content_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Type"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"body": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Body"
},
"html_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Html Url"
},
"distance": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Distance"
},
"readable_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Readable Type"
},
"relevance": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Relevance"
}
},
"title": "SearchResultItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"results": {
"items": {
"$ref": "#/$defs/SearchResultItem"
},
"title": "Results",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchCourseContentOutput",
"type": "object"
}
```
### Parameters
The ID of the course containing the assignment.
The ID of the assignment to update.
The new name of the assignment.
The new description of the assignment (supports HTML).
Submission type: online_quiz, none, on_paper, discussion_topic, external_tool, online_upload, online_text_entry, online_url, media_recording, student_annotation.
Whether to notify students of the update.
Maximum points possible on the assignment.
Grading strategy: pass_fail, percent, letter_grade, gpa_scale, points, not_graded.
Due date/time in ISO 8601 format (e.g. 2014-10-21T18:48:00Z).
Whether to omit this assignment from the student's final grade.
Number of submission attempts allowed (-1 for unlimited).
### Response
```json
{
"$defs": {
"AssignmentSummary": {
"additionalProperties": false,
"description": "A Canvas assignment.",
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"due_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Due At"
},
"points_possible": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Points Possible"
},
"grading_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Grading Type"
},
"submission_types": {
"items": {
"type": "string"
},
"title": "Submission Types",
"type": "array"
},
"course_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Course Id"
},
"allowed_attempts": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Allowed Attempts"
},
"omit_from_final_grade": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Omit From Final Grade"
}
},
"title": "AssignmentSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"assignment": {
"anyOf": [
{
"$ref": "#/$defs/AssignmentSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UpdateAssignmentOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limits**: Canvas enforces per-user rate limits (typically 700 requests per 10 minutes for the default configuration, varies by institution).
- **Pagination**: List endpoints may return paginated results; current implementation fetches the first page.
- **Error model**: Non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Links
- [Instructure Canvas LMS](https://www.instructure.com/canvas)
---
# Intercom Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/intercom
Customer communication platform for support, engagement, and marketing automation.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/intercom/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Intercom** to any ModuleX agent or workflow. Customer-communication integration for Intercom: contacts (CRUD + search), notes, tags, admins, conversations (CRUD + search), and inbound/outbound messaging. All against `api.intercom.io` with the `Intercom-Version: 2.12` header on every request.
**Categories**: Customer Support · CRM & Customer · Communication · Automation · Development · **Auth**: Access Token · **Actions**: 13
## Authentication
### Access Token
Use your Intercom Access Token for direct authentication
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Access Token | Your Intercom Access Token | Yes | `dG9rOjxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
| API Base URL | Intercom API base URL (optional — leave empty for https://api.intercom.io US default). Set to https://api.eu.intercom.io for EU workspaces or https://api.au.intercom.io for Australia. | No | `https://api.intercom.io` |
## Available Actions
### Parameters
The unique identifier for the contact
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "GetContactOutput",
"type": "object"
}
```
### Parameters
Field to search by (email, name, phone, role, external_id, etc.) (Default: `email`)
Query operator (=, !=, >, <, ~, !~, IN, NIN) (Default: `=`)
Value to search for
Results per page (max 150) (Default: `50`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"contacts": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Contacts",
"type": "array"
},
"total_count": {
"default": 0,
"title": "Total Count",
"type": "integer"
},
"pages": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Pages"
}
},
"required": [
"success"
],
"title": "SearchContactsOutput",
"type": "object"
}
```
### Parameters
The contact's email address
Role of the contact ('user' or 'lead')
A unique identifier from your system
The contact's phone number
The contact's name
URL of the avatar image
Whether the contact is unsubscribed from emails
Custom attributes for the contact
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"action_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Action Type"
},
"contact": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Contact"
}
},
"required": [
"success"
],
"title": "UpsertContactOutput",
"type": "object"
}
```
### Parameters
The contact's unique Intercom identifier
The note content (supports HTML)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "CreateNoteOutput",
"type": "object"
}
```
### Parameters
The contact's unique Intercom identifier
The tag's unique identifier
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "AddTagToContactOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "ListTagsOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "ListAdminsOutput",
"type": "object"
}
```
### Parameters
The conversation's unique identifier
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "GetConversationOutput",
"type": "object"
}
```
### Parameters
Conversations per page (max 150) (Default: `20`)
Pagination cursor from previous response
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"conversations": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Conversations",
"type": "array"
},
"pages": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Pages"
}
},
"required": [
"success"
],
"title": "ListConversationsOutput",
"type": "object"
}
```
### Parameters
Field to search by (created_at, state, source.type, etc.) (Default: `created_at`)
Query operator (=, !=, >, <, IN, NIN) (Default: `>`)
Value to search for (timestamp for date fields)
Results per page (max 150) (Default: `20`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"conversations": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Conversations",
"type": "array"
},
"total_count": {
"default": 0,
"title": "Total Count",
"type": "integer"
},
"pages": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Pages"
}
},
"required": [
"success"
],
"title": "SearchConversationsOutput",
"type": "object"
}
```
### Parameters
The contact's unique Intercom identifier
The message content
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "SendIncomingMessageOutput",
"type": "object"
}
```
### Parameters
The admin's unique identifier
The contact's unique identifier
Recipient type ('user' or 'lead') (Default: `user`)
Message type ('in_app' or 'email') (Default: `in_app`)
Subject/title of the message
Message content (HTML and plaintext supported)
Template style ('plain' or 'personal') (Default: `personal`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "SendMessageToContactOutput",
"type": "object"
}
```
### Parameters
The conversation's unique identifier
Type of reply ('user' or 'admin')
Message type ('comment' or 'note', note only for admin) (Default: `comment`)
The reply content
Admin ID (required if reply_type is 'admin')
Intercom user ID (for user reply)
List of image URLs to attach (max 10)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "ReplyToConversationOutput",
"type": "object"
}
```
## Limits & Quotas
- `per_page` is clamped at 150 (Intercom's max).
- `reply_to_conversation` allows up to 10 attachment URLs (Intercom's
max).
- Failures (non-2xx, exceptions) surface as `success=False` + `error`.
## Related integrations
## Links
- [Intercom](https://www.intercom.com)
---
# Jina AI Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/jina-ai
AI-powered search foundation with embeddings, reranking, web reading, search, deep research, text segmentation, and zero-shot classification capabilities.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/jina_ai/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Jina AI** to any ModuleX agent or workflow. AI-powered search foundation tools against Jina AI's REST surfaces: embeddings, rerank, web reader, web search, deep search, text segmentation, and zero-shot classification. Each capability lives on a different subdomain — the tool code routes to the correct one per action.
**Categories**: Web Search & Scraping · Ai · Embeddings · Nlp · Research · **Auth**: API Key, ModuleX Managed Key · **Actions**: 7
## Authentication
### API Key Authentication
Authenticate using your Jina AI API key. Get your free API key at https://jina.ai/?sui=apikey
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Jina AI API Key | Your Jina AI API key for authentication. Get your free key at https://jina.ai/?sui=apikey | Yes | `jina_xxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
### ModuleX Managed Key
Use ModuleX's managed API keys with usage tracked against your weekly credit limit
## Available Actions
### Parameters
Array of input strings or objects with 'text', 'image', or 'pdf' keys
Embedding model to use (Default: `jina-embeddings-v3`)
Task optimization type
Truncate embeddings to specified size
Enable late chunking mode (Default: `false`)
Auto-truncate content beyond max length (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GenerateEmbeddingsOutput",
"type": "object"
}
```
### Parameters
Search query to rank documents against
Documents to rerank (strings or objects)
Reranker model to use (Default: `jina-reranker-v2-base-multilingual`)
Number of top results to return
Include document text in response (Default: `true`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "RerankDocumentsOutput",
"type": "object"
}
```
### Parameters
The URL to read and parse
Output format (Default: `markdown`)
CSS selectors to focus on specific elements
CSS selectors to exclude from page
CSS selectors to wait for before returning
Gather all links at the end of response (Default: `false`)
Gather all images at the end of response (Default: `false`)
Maximum time in seconds to wait for webpage to load
Bypass cache for fresh retrieval (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"content": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content"
},
"links": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Links"
},
"images": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Images"
},
"usage": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Usage"
}
},
"required": [
"success"
],
"title": "ReadWebpageOutput",
"type": "object"
}
```
### Parameters
The search query to execute
Limit search to specific domain (e.g. 'github.com')
Output format (Default: `markdown`)
Maximum number of results to return
Two-letter country code for localized results
Two-letter language code for search
Include links summary (Default: `false`)
Include images summary (Default: `false`)
Bypass cache for real-time data (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
},
"results": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Results",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "WebSearchOutput",
"type": "object"
}
```
### Parameters
Research query or question to investigate
Reasoning effort level (low, medium, high) (Default: `medium`)
Maximum tokens for the process (overrides reasoning_effort)
Maximum retries for problem solving
Force deeper search even for simple queries (Default: `false`)
Maximum URLs in final answer
Domains to prioritize for content retrieval
Domains to exclude from content retrieval
Only retrieve content from these domains
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "DeepSearchOutput",
"type": "object"
}
```
### Parameters
Text content to segment
Tokenizer to use (Default: `cl100k_base`)
Include tokens and IDs in response (Default: `false`)
Segment into semantic chunks (Default: `true`)
Maximum characters per chunk (Default: `1000`)
Return only first N tokens (exclusive with tail)
Return only last N tokens (exclusive with head)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
},
"num_tokens": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Num Tokens"
},
"num_chunks": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Num Chunks"
},
"chunks": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Chunks"
},
"chunk_positions": {
"anyOf": [
{
"items": {
"items": {
"type": "integer"
},
"type": "array"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Chunk Positions"
},
"tokens": {
"anyOf": [
{
"items": {},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Tokens"
},
"tokenizer": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Tokenizer"
},
"usage": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Usage"
}
},
"required": [
"success"
],
"title": "SegmentTextOutput",
"type": "object"
}
```
### Parameters
Array of texts or image objects to classify
List of classification categories
Classification model (Default: `jina-embeddings-v3`)
Existing classifier ID to reuse
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
},
"classifications": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Classifications",
"type": "array"
},
"usage": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Usage"
}
},
"required": [
"success"
],
"title": "ClassifyOutput",
"type": "object"
}
```
## Limits & Quotas
- Per-endpoint subdomains:
`api.jina.ai/v1/embeddings`, `api.jina.ai/v1/rerank`,
`r.jina.ai/`, `s.jina.ai/`,
`deepsearch.jina.ai/v1/chat/completions`,
`segment.jina.ai/`, `api.jina.ai/v1/classify`.
- Reader and Search expect their configuration via `X-*` request
headers (return format, target selectors, cache bypass, etc.) —
preserved verbatim from the legacy implementation.
- Deep search timeout is 300s (the API genuinely takes that long for
high-effort queries); reader/search use 120s; everything else uses
60s.
- Standard plan rate limits (from the legacy JSON's `rate_limits`
block): embeddings/rerank 500 RPM, reader 200 RPM, search 40 RPM,
classify 20 RPM, segment 200 RPM. Premium is 4-10× higher.
## Related integrations
## Links
- [Jina AI](https://jina.ai)
---
# Jira Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/jira
Atlassian Jira Cloud project tracking and issue management platform
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/jira/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Jira** to any ModuleX agent or workflow. Atlassian Jira Cloud project tracking and issue management integration against the Jira REST API v3 (`api.atlassian.com/ex/jira/{cloudId}/rest/api/3`) and Jira Agile API (`api.atlassian.com/ex/jira/{cloudId}/rest/agile/1.0`).
**Categories**: Project & Task Management · Project Management · Developer Tools & Infrastructure · Productivity & Collaboration · **Auth**: OAuth2 · **Actions**: 38
## Authentication
### OAuth2 Authentication
Connect using Atlassian OAuth2 (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Atlassian OAuth App Client ID | Yes | `-` |
| Client Secret | Atlassian OAuth App Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://auth.atlassian.com/authorize`
- **Token URL**: `https://auth.atlassian.com/oauth/token`
- **Scopes**: `read:jira-work`, `write:jira-work`, `read:jira-user`, `manage:jira-project`, `manage:jira-configuration`, `offline_access`
## Available Actions
### Parameters
The cloud ID of the Jira site
The ID or key of the issue
A file URL to attach to the issue
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"filename": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Filename"
},
"mime_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mime Type"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
}
},
"required": [
"success"
],
"title": "AddAttachmentToIssueOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID or key of the issue
The comment text in plain text (converted to Atlassian Document Format)
The comment text in Atlassian Document Format (JSON object). Overrides comment if both provided
The group or role to which this comment is visible
A JSON array of comment properties
Extra properties of any type to include
Use 'renderedBody' to get comment body rendered in HTML
### Response
```json
{
"$defs": {
"CommentSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
},
"body": {
"anyOf": [
{},
{
"type": "null"
}
],
"default": null,
"title": "Body"
},
"author": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Author"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
}
},
"title": "CommentSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"comment": {
"anyOf": [
{
"$ref": "#/$defs/CommentSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "AddCommentToIssueOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID or key of the issue
An array of file URLs to attach to the issue. Each element is a string URL
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"attachments": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Attachments",
"type": "array"
}
},
"required": [
"success"
],
"title": "AddMultipleAttachmentsToIssueOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID or key of the issue
The account ID of the user to add as watcher
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
}
},
"required": [
"success"
],
"title": "AddWatcherToIssueOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID or key of the issue
The account ID of the user to assign
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
}
},
"required": [
"success"
],
"title": "AssignIssueOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
A list of issue IDs to check against the JQL queries. Elements are integers
A list of JQL query strings to check the issues against
### Response
```json
{
"$defs": {
"JqlMatchResult": {
"additionalProperties": false,
"properties": {
"issue_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Issue Id"
},
"matched_jqls": {
"items": {
"type": "string"
},
"title": "Matched Jqls",
"type": "array"
}
},
"title": "JqlMatchResult",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"matches": {
"items": {
"$ref": "#/$defs/JqlMatchResult"
},
"title": "Matches",
"type": "array"
}
},
"required": [
"success"
],
"title": "CheckIssuesAgainstJqlOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The JQL query to count issues. Must be bounded (e.g. project = ABC)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
}
},
"required": [
"success"
],
"title": "CountIssuesUsingJqlOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID of the custom field
The ID of the field context
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"options": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Options",
"type": "array"
}
},
"required": [
"success"
],
"title": "CreateCustomFieldOptionsContextOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID of the board the sprint will be created on
The name of the sprint
The goal of the sprint
The start date in ISO 8601 format (e.g. 2024-01-01T00:00:00.000Z)
The end date in ISO 8601 format (e.g. 2024-01-15T00:00:00.000Z)
### Response
```json
{
"$defs": {
"SprintSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"start_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Start Date"
},
"end_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "End Date"
},
"complete_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Complete Date"
},
"goal": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Goal"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
}
},
"title": "SprintSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"sprint": {
"anyOf": [
{
"$ref": "#/$defs/SprintSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateFutureSprintOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The project ID
The issue type ID
Whether the project is added to the user's Recently viewed project list
Additional issue history details
Details of issue properties to add or update (JSON array)
A map of field name to operations list for issue screen fields
Extra fields to include in the issue body (e.g. summary, description, labels, priority)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Key"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
}
},
"required": [
"success"
],
"title": "CreateIssueOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The project ID
The unique name of the version. Max 255 characters
The description of the version
Indicates that the version is archived
The start date (yyyy-mm-dd)
The release date (yyyy-mm-dd)
Expand options: operations, issuesstatus
### Response
```json
{
"$defs": {
"VersionSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"archived": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Archived"
},
"released": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Released"
},
"start_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Start Date"
},
"release_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Release Date"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
}
},
"title": "VersionSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"version": {
"anyOf": [
{
"$ref": "#/$defs/VersionSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateVersionOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The project ID or key
Whether this project is placed in the Jira recycle bin for recovery
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
}
},
"required": [
"success"
],
"title": "DeleteProjectOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
Returns the user's most recently accessed projects (max 20)
Issue properties to include (JSON array)
Expand options: description, issueTypes, lead, projectKeys
### Response
```json
{
"$defs": {
"ProjectSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Key"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"project_type_key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Project Type Key"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
}
},
"title": "ProjectSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"projects": {
"items": {
"$ref": "#/$defs/ProjectSummary"
},
"title": "Projects",
"type": "array"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
}
},
"required": [
"success"
],
"title": "GetAllProjectsOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID of the board
### Response
```json
{
"$defs": {
"BoardSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"board_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Board Type"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
}
},
"title": "BoardSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"board": {
"anyOf": [
{
"$ref": "#/$defs/BoardSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetBoardOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"CloudSite": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"scopes": {
"items": {
"type": "string"
},
"title": "Scopes",
"type": "array"
},
"avatar_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Avatar Url"
}
},
"title": "CloudSite",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"sites": {
"items": {
"$ref": "#/$defs/CloudSite"
},
"title": "Sites",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetCloudIdOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
### Response
```json
{
"$defs": {
"UserSummary": {
"additionalProperties": false,
"properties": {
"account_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Account Id"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"email_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Address"
},
"active": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Active"
},
"avatar_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Avatar Url"
},
"account_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Account Type"
}
},
"title": "UserSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"user": {
"anyOf": [
{
"$ref": "#/$defs/UserSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetCurrentUserOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID or key of the issue
Comma-separated list of fields to return. *all or *navigable for all or navigable fields
Whether fields are referenced by keys rather than IDs
Issue properties to include (comma-separated or *all)
Whether project is added to Recently viewed
Expand options: renderedFields, names, schema, transitions, editmeta, changelog, versionedRepresentations
### Response
```json
{
"$defs": {
"IssueSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Key"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"issue_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Issue Type"
},
"priority": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Priority"
},
"assignee": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Assignee"
},
"reporter": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Reporter"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"fields": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Fields"
}
},
"title": "IssueSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"issue": {
"anyOf": [
{
"$ref": "#/$defs/IssueSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetIssueOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
A string to match against issue text fields
A JQL query defining a list of issues to search within
The key of an issue to exclude from results
The ID of a project that results must belong to
Whether to include subtasks in suggestions
Whether to include the parent issue when currentIssueKey is a subtask
### Response
```json
{
"$defs": {
"IssueSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Key"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"issue_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Issue Type"
},
"priority": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Priority"
},
"assignee": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Assignee"
},
"reporter": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Reporter"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"fields": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Fields"
}
},
"title": "IssueSummary",
"type": "object"
},
"SuggestionSection": {
"additionalProperties": false,
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Label"
},
"issues": {
"items": {
"$ref": "#/$defs/IssueSummary"
},
"title": "Issues",
"type": "array"
}
},
"title": "SuggestionSection",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"sections": {
"items": {
"$ref": "#/$defs/SuggestionSection"
},
"title": "Sections",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetIssuePickerSuggestionsOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The project ID to filter issue types
### Response
```json
{
"$defs": {
"IssueTypeSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"subtask": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Subtask"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
}
},
"title": "IssueTypeSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"issue_types": {
"items": {
"$ref": "#/$defs/IssueTypeSummary"
},
"title": "Issue Types",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetIssueTypesOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID of the sprint
### Response
```json
{
"$defs": {
"SprintSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"start_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Start Date"
},
"end_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "End Date"
},
"complete_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Complete Date"
},
"goal": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Goal"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
}
},
"title": "SprintSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"sprint": {
"anyOf": [
{
"$ref": "#/$defs/SprintSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetSprintOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID of the long-running async task
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"progress": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Progress"
},
"result": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
},
"task_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Task Id"
}
},
"required": [
"success"
],
"title": "GetTaskOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID or key of the issue
The ID of a specific transition to retrieve
Whether transitions with Hide From User Condition are included
Whether details of failing-condition transitions are included
Whether transitions are sorted by ops-bar sequence then category
Expand options: transitions.fields
### Response
```json
{
"$defs": {
"TransitionSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"to_status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "To Status"
},
"has_screen": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has Screen"
}
},
"title": "TransitionSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"transitions": {
"items": {
"$ref": "#/$defs/TransitionSummary"
},
"title": "Transitions",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetTransitionsOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The account ID of the user
Expand options: groups, applicationRoles
### Response
```json
{
"$defs": {
"UserSummary": {
"additionalProperties": false,
"properties": {
"account_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Account Id"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"email_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Address"
},
"active": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Active"
},
"avatar_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Avatar Url"
},
"account_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Account Type"
}
},
"title": "UserSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"user": {
"anyOf": [
{
"$ref": "#/$defs/UserSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetUserOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
Filter for a name or term
### Response
```json
{
"$defs": {
"UserSummary": {
"additionalProperties": false,
"properties": {
"account_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Account Id"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"email_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Address"
},
"active": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Active"
},
"avatar_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Avatar Url"
},
"account_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Account Type"
}
},
"title": "UserSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"users": {
"items": {
"$ref": "#/$defs/UserSummary"
},
"title": "Users",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetUsersOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID of the board
The starting index of the returned issues. Base index: 0
The maximum number of issues to return
Filters results using a JQL query
Comma-separated list of fields to return per issue
Expand options for additional information
### Response
```json
{
"$defs": {
"IssueSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Key"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"issue_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Issue Type"
},
"priority": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Priority"
},
"assignee": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Assignee"
},
"reporter": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Reporter"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"fields": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Fields"
}
},
"title": "IssueSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"issues": {
"items": {
"$ref": "#/$defs/IssueSummary"
},
"title": "Issues",
"type": "array"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"start_at": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Start At"
},
"max_results": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Max Results"
}
},
"required": [
"success"
],
"title": "ListBoardIssuesOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The starting index of the returned boards. Base index: 0
The maximum number of boards to return
Filters by board type: scrum, kanban, simple
Filters results to boards matching this name
Filters results to boards relevant to a project
### Response
```json
{
"$defs": {
"BoardSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"board_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Board Type"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
}
},
"title": "BoardSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"boards": {
"items": {
"$ref": "#/$defs/BoardSummary"
},
"title": "Boards",
"type": "array"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"start_at": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Start At"
},
"max_results": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Max Results"
}
},
"required": [
"success"
],
"title": "ListBoardsOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID of the board
The ID of the epic
The starting index of the returned issues. Base index: 0
The maximum number of issues to return
Filters results using a JQL query
Comma-separated list of fields to return per issue
Expand options for additional information
### Response
```json
{
"$defs": {
"IssueSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Key"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"issue_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Issue Type"
},
"priority": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Priority"
},
"assignee": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Assignee"
},
"reporter": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Reporter"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"fields": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Fields"
}
},
"title": "IssueSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"issues": {
"items": {
"$ref": "#/$defs/IssueSummary"
},
"title": "Issues",
"type": "array"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"start_at": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Start At"
},
"max_results": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Max Results"
}
},
"required": [
"success"
],
"title": "ListEpicIssuesOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID of the board
The starting index of the returned epics. Base index: 0
The maximum number of epics to return
Filter to epics that are done or not done
### Response
```json
{
"$defs": {
"EpicSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Key"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"done": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Done"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
}
},
"title": "EpicSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"epics": {
"items": {
"$ref": "#/$defs/EpicSummary"
},
"title": "Epics",
"type": "array"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"start_at": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Start At"
},
"max_results": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Max Results"
}
},
"required": [
"success"
],
"title": "ListEpicsOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID or key of the issue
Order results by a field. Valid: created, +created, -created
Expand options: renderedBody
### Response
```json
{
"$defs": {
"CommentSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
},
"body": {
"anyOf": [
{},
{
"type": "null"
}
],
"default": null,
"title": "Body"
},
"author": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Author"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
}
},
"title": "CommentSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"comments": {
"items": {
"$ref": "#/$defs/CommentSummary"
},
"title": "Comments",
"type": "array"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"start_at": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Start At"
},
"max_results": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Max Results"
}
},
"required": [
"success"
],
"title": "ListIssueCommentsOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
}
},
"required": [
"success"
],
"title": "ListLabelsOptionsOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID of the sprint
The starting index of the returned issues. Base index: 0
The maximum number of issues to return
Filters results using a JQL query
Comma-separated list of fields to return per issue
Expand options for additional information
### Response
```json
{
"$defs": {
"IssueSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Key"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"issue_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Issue Type"
},
"priority": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Priority"
},
"assignee": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Assignee"
},
"reporter": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Reporter"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"fields": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Fields"
}
},
"title": "IssueSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"issues": {
"items": {
"$ref": "#/$defs/IssueSummary"
},
"title": "Issues",
"type": "array"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"start_at": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Start At"
},
"max_results": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Max Results"
}
},
"required": [
"success"
],
"title": "ListSprintIssuesOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID of the board
The starting index of the returned sprints. Base index: 0
The maximum number of sprints to return
Filter by sprint states: future, active, closed (comma-separated)
### Response
```json
{
"$defs": {
"SprintSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"start_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Start Date"
},
"end_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "End Date"
},
"complete_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Complete Date"
},
"goal": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Goal"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
}
},
"title": "SprintSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"sprints": {
"items": {
"$ref": "#/$defs/SprintSummary"
},
"title": "Sprints",
"type": "array"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"start_at": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Start At"
},
"max_results": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Max Results"
}
},
"required": [
"success"
],
"title": "ListSprintsOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID of the sprint
The IDs or keys of the issues to move to the sprint. Each element is a string
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
}
},
"required": [
"success"
],
"title": "MoveIssuesToSprintOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The JQL query to search for issues
Maximum number of issues to return (default 50, max 5000)
Comma-separated list of fields to return
Expand options: renderedFields, names, schema, transitions, editmeta, changelog, versionedRepresentations
Comma-separated list of issue properties to include (max 5)
Reference fields by key rather than ID
Fail early if not all field data can be retrieved
### Response
```json
{
"$defs": {
"IssueSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Key"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"issue_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Issue Type"
},
"priority": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Priority"
},
"assignee": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Assignee"
},
"reporter": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Reporter"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"fields": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Fields"
}
},
"title": "IssueSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"issues": {
"items": {
"$ref": "#/$defs/IssueSummary"
},
"title": "Issues",
"type": "array"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"start_at": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Start At"
},
"max_results": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Max Results"
}
},
"required": [
"success"
],
"title": "SearchIssuesWithJqlOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The JQL query to search for issues
Maximum number of items per page
Token for pagination from a previous response
Fields to return per issue. Elements are strings. Example: ['summary', 'status']
Expand options: renderedFields, names, schema, transitions, editmeta, changelog, versionedRepresentations
Issue property keys to include (max 5). Elements are strings
Reference fields by key rather than ID
Issue IDs/keys for read-after-write consistency. Elements are strings
### Response
```json
{
"$defs": {
"IssueSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Key"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"issue_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Issue Type"
},
"priority": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Priority"
},
"assignee": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Assignee"
},
"reporter": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Reporter"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"fields": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Fields"
}
},
"title": "IssueSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"issues": {
"items": {
"$ref": "#/$defs/IssueSummary"
},
"title": "Issues",
"type": "array"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
},
"next_page_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page Token"
}
},
"required": [
"success"
],
"title": "SearchIssuesWithJqlPostOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID or key of the issue
The transition ID to perform
List of issue screen fields to update during transition
Operations to perform on issue screen fields
Additional issue history details
Issue properties to add or update (JSON)
Extra properties of any type
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
}
},
"required": [
"success"
],
"title": "TransitionIssueOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The ID or key of the issue
The ID of the comment to update
The comment text in Atlassian Document Format (JSON). Overrides comment if both provided
The comment text (plain text)
The group or role to which this comment is visible
Comment properties (JSON array)
Extra properties of any type
Whether users are notified when comment is updated
Expand options: renderedBody
### Response
```json
{
"$defs": {
"CommentSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"self_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Url"
},
"body": {
"anyOf": [
{},
{
"type": "null"
}
],
"default": null,
"title": "Body"
},
"author": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Author"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
}
},
"title": "CommentSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"comment": {
"anyOf": [
{
"$ref": "#/$defs/CommentSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UpdateCommentOutput",
"type": "object"
}
```
### Parameters
The cloud ID of the Jira site
The project ID
The ID or key of the issue
The issue type ID
Whether a notification email is sent to watchers
Override screen security to enable hidden fields
Override editable flag to enable uneditable fields
The ID of the transition to undertake
Whether the transition is looped
Additional issue history details
Issue properties to add or update (JSON array)
A map of field name to operations list
Extra fields to update (e.g. summary, description)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
}
},
"required": [
"success"
],
"title": "UpdateIssueOutput",
"type": "object"
}
```
## Limits & Quotas
- **Standard rate limit**: Jira Cloud REST API allows approximately 100 requests per 10 seconds per user per app.
- **Concurrent requests**: Maximum 10 concurrent requests per user per app.
- **Search (JQL)**: Maximum 5000 results per search request.
- **Attachments**: Maximum 10 MB per file (default; configurable by site admin).
- **Error model**: non-2xx responses raise `httpx.HTTPStatusError` (Pattern A). The error includes the status code and response body for debugging.
## Related integrations
## Links
- [Jira](https://www.atlassian.com/software/jira)
---
# Kalshi Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/kalshi
Access Kalshi prediction markets and trade event contracts: retrieve markets, events, series, orderbooks, trades, candlesticks, account balance, positions, orders, fills, settlements, exchange status, and place, cancel, or amend orders.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/kalshi/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Kalshi** to any ModuleX agent or workflow. Access Kalshi prediction markets and trade event contracts against the Kalshi Trade API v2 (`api.elections.kalshi.com/trade-api/v2`). Retrieve markets, events, series, orderbooks, trades, and candlesticks; manage your balance, positions, orders, fills, and settlements; check exchange status; and place, cancel, or amend orders.
**Categories**: Finance & Payments · Prediction Markets · Data Analytics · **Auth**: API Key · **Actions**: 22
## Authentication
### API Key Authentication
Authenticate with a Kalshi API key id and its RSA private key. Each request is signed with the private key (RSA-PSS over SHA-256); the signing material never leaves the runtime.
Sign in at https://kalshi.com and open Account → API Keys.
Create a new API key; download the RSA private key (PEM) and copy the Key ID.
Paste the Key ID into KALSHI_KEY_ID below.
Paste the full PEM private key into KALSHI_PRIVATE_KEY below.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| API Key ID | Your Kalshi API Key ID from Account → API Keys | Yes | `-` |
| RSA Private Key (PEM) | Your Kalshi RSA private key in PEM format | Yes | `-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----` |
## Available Actions
### Parameters
Filter by market status: "unopened", "open", "closed", "settled"
Filter by series ticker
Filter by event ticker
Min created timestamp (Unix seconds)
Max created timestamp (Unix seconds)
Min updated timestamp (Unix seconds)
Min close timestamp (Unix seconds)
Max close timestamp (Unix seconds)
Min settled timestamp (Unix seconds)
Max settled timestamp (Unix seconds)
Comma-separated list of market tickers
Multivariate event filter: "only" or "exclude"
Number of results to return (1-1000)
Pagination cursor from a previous response
### Response
```json
{
"$defs": {
"Market": {
"additionalProperties": false,
"description": "A single market row (Trade API v2 shape).",
"properties": {
"ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ticker"
},
"event_ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Event Ticker"
},
"market_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Market Type"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"subtitle": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subtitle"
},
"yes_sub_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Sub Title"
},
"no_sub_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "No Sub Title"
},
"open_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Open Time"
},
"close_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Close Time"
},
"expected_expiration_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Expected Expiration Time"
},
"expiration_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Expiration Time"
},
"latest_expiration_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Latest Expiration Time"
},
"settlement_timer_seconds": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Settlement Timer Seconds"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"response_price_units": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Response Price Units"
},
"notional_value": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Notional Value"
},
"tick_size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Tick Size"
},
"yes_bid": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Bid"
},
"yes_ask": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Ask"
},
"no_bid": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "No Bid"
},
"no_ask": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "No Ask"
},
"last_price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Price"
},
"previous_yes_bid": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Previous Yes Bid"
},
"previous_yes_ask": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Previous Yes Ask"
},
"previous_price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Previous Price"
},
"volume": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Volume"
},
"volume_24h": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Volume 24H"
},
"liquidity": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Liquidity"
},
"open_interest": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Open Interest"
},
"result": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
},
"cap_strike": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Cap Strike"
},
"floor_strike": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Floor Strike"
},
"can_close_early": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Close Early"
},
"expiration_value": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Expiration Value"
},
"category": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Category"
},
"risk_limit_cents": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Risk Limit Cents"
},
"strike_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Strike Type"
},
"rules_primary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rules Primary"
},
"rules_secondary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rules Secondary"
},
"settlement_source_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Settlement Source Url"
},
"custom_strike": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Custom Strike"
},
"underlying": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Underlying"
},
"settlement_value": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Settlement Value"
},
"cfd_contract_size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Cfd Contract Size"
},
"yes_fee_fp": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Fee Fp"
},
"no_fee_fp": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "No Fee Fp"
},
"last_price_fp": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Price Fp"
},
"yes_bid_fp": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Bid Fp"
},
"yes_ask_fp": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Ask Fp"
},
"no_bid_fp": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "No Bid Fp"
},
"no_ask_fp": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "No Ask Fp"
}
},
"title": "Market",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"markets": {
"items": {
"$ref": "#/$defs/Market"
},
"title": "Markets",
"type": "array"
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cursor"
}
},
"required": [
"success"
],
"title": "GetMarketsOutput",
"type": "object"
}
```
### Parameters
Market ticker identifier (e.g., 'KXBTC-24DEC31')
### Response
```json
{
"$defs": {
"Market": {
"additionalProperties": false,
"description": "A single market row (Trade API v2 shape).",
"properties": {
"ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ticker"
},
"event_ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Event Ticker"
},
"market_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Market Type"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"subtitle": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subtitle"
},
"yes_sub_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Sub Title"
},
"no_sub_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "No Sub Title"
},
"open_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Open Time"
},
"close_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Close Time"
},
"expected_expiration_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Expected Expiration Time"
},
"expiration_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Expiration Time"
},
"latest_expiration_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Latest Expiration Time"
},
"settlement_timer_seconds": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Settlement Timer Seconds"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"response_price_units": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Response Price Units"
},
"notional_value": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Notional Value"
},
"tick_size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Tick Size"
},
"yes_bid": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Bid"
},
"yes_ask": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Ask"
},
"no_bid": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "No Bid"
},
"no_ask": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "No Ask"
},
"last_price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Price"
},
"previous_yes_bid": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Previous Yes Bid"
},
"previous_yes_ask": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Previous Yes Ask"
},
"previous_price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Previous Price"
},
"volume": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Volume"
},
"volume_24h": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Volume 24H"
},
"liquidity": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Liquidity"
},
"open_interest": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Open Interest"
},
"result": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
},
"cap_strike": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Cap Strike"
},
"floor_strike": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Floor Strike"
},
"can_close_early": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Close Early"
},
"expiration_value": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Expiration Value"
},
"category": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Category"
},
"risk_limit_cents": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Risk Limit Cents"
},
"strike_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Strike Type"
},
"rules_primary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rules Primary"
},
"rules_secondary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Rules Secondary"
},
"settlement_source_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Settlement Source Url"
},
"custom_strike": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Custom Strike"
},
"underlying": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Underlying"
},
"settlement_value": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Settlement Value"
},
"cfd_contract_size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Cfd Contract Size"
},
"yes_fee_fp": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Fee Fp"
},
"no_fee_fp": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "No Fee Fp"
},
"last_price_fp": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Price Fp"
},
"yes_bid_fp": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Bid Fp"
},
"yes_ask_fp": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Ask Fp"
},
"no_bid_fp": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "No Bid Fp"
},
"no_ask_fp": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "No Ask Fp"
}
},
"title": "Market",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"market": {
"anyOf": [
{
"$ref": "#/$defs/Market"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetMarketOutput",
"type": "object"
}
```
### Parameters
Filter by event status: "open", "closed", "settled"
Filter by series ticker
Include nested markets: "true" or "false"
Include milestones: "true" or "false"
Min close timestamp (Unix seconds)
Number of results to return (1-200)
Pagination cursor from a previous response
### Response
```json
{
"$defs": {
"Event": {
"additionalProperties": false,
"description": "An event row (Trade API v2 shape).",
"properties": {
"event_ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Event Ticker"
},
"series_ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Series Ticker"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"sub_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sub Title"
},
"mutually_exclusive": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Mutually Exclusive"
},
"category": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Category"
},
"collateral_return_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Collateral Return Type"
},
"strike_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Strike Date"
},
"strike_period": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Strike Period"
},
"available_on_brokers": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Available On Brokers"
},
"product_metadata": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Product Metadata"
},
"markets": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Markets",
"type": "array"
}
},
"title": "Event",
"type": "object"
},
"Milestone": {
"additionalProperties": false,
"description": "An event milestone (returned by get_events when requested).",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"category": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Category"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"start_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Start Date"
},
"end_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "End Date"
},
"notification_message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Notification Message"
},
"primary_event_tickers": {
"items": {
"type": "string"
},
"title": "Primary Event Tickers",
"type": "array"
},
"related_event_tickers": {
"items": {
"type": "string"
},
"title": "Related Event Tickers",
"type": "array"
},
"last_updated_ts": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Updated Ts"
}
},
"title": "Milestone",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"events": {
"items": {
"$ref": "#/$defs/Event"
},
"title": "Events",
"type": "array"
},
"milestones": {
"items": {
"$ref": "#/$defs/Milestone"
},
"title": "Milestones",
"type": "array"
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cursor"
}
},
"required": [
"success"
],
"title": "GetEventsOutput",
"type": "object"
}
```
### Parameters
Event ticker identifier
Include nested markets: "true" or "false"
### Response
```json
{
"$defs": {
"Event": {
"additionalProperties": false,
"description": "An event row (Trade API v2 shape).",
"properties": {
"event_ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Event Ticker"
},
"series_ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Series Ticker"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"sub_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sub Title"
},
"mutually_exclusive": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Mutually Exclusive"
},
"category": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Category"
},
"collateral_return_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Collateral Return Type"
},
"strike_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Strike Date"
},
"strike_period": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Strike Period"
},
"available_on_brokers": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Available On Brokers"
},
"product_metadata": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Product Metadata"
},
"markets": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Markets",
"type": "array"
}
},
"title": "Event",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"event": {
"anyOf": [
{
"$ref": "#/$defs/Event"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetEventOutput",
"type": "object"
}
```
### Parameters
Kalshi API Key ID (provided by the credential system)
Kalshi RSA private key in PEM format (provided by the credential system)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"balance": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Balance"
},
"portfolio_value": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Portfolio Value"
},
"updated_ts": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated Ts"
}
},
"required": [
"success"
],
"title": "GetBalanceOutput",
"type": "object"
}
```
### Parameters
Kalshi API Key ID (provided by the credential system)
Kalshi RSA private key in PEM format (provided by the credential system)
Filter by market ticker
Filter by event ticker (max 10, comma-separated)
Comma-separated non-zero fields: position, total_traded
Subaccount identifier
Number of results to return (1-1000)
Pagination cursor from a previous response
### Response
```json
{
"$defs": {
"EventPosition": {
"additionalProperties": false,
"properties": {
"event_ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Event Ticker"
},
"event_exposure": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Event Exposure"
},
"realized_pnl": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Realized Pnl"
},
"total_cost": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Cost"
}
},
"title": "EventPosition",
"type": "object"
},
"MarketPosition": {
"additionalProperties": false,
"properties": {
"ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ticker"
},
"event_ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Event Ticker"
},
"event_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Event Title"
},
"market_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Market Title"
},
"position": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Position"
},
"market_exposure": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Market Exposure"
},
"realized_pnl": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Realized Pnl"
},
"total_traded": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Traded"
},
"resting_orders_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Resting Orders Count"
},
"fees_paid": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Fees Paid"
}
},
"title": "MarketPosition",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"market_positions": {
"items": {
"$ref": "#/$defs/MarketPosition"
},
"title": "Market Positions",
"type": "array"
},
"event_positions": {
"items": {
"$ref": "#/$defs/EventPosition"
},
"title": "Event Positions",
"type": "array"
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cursor"
}
},
"required": [
"success"
],
"title": "GetPositionsOutput",
"type": "object"
}
```
### Parameters
Kalshi API Key ID (provided by the credential system)
Kalshi RSA private key in PEM format (provided by the credential system)
Filter by market ticker
Filter by event ticker (max 10, comma-separated)
Filter by status: "resting", "canceled", "executed"
Minimum timestamp filter (Unix timestamp)
Maximum timestamp filter (Unix timestamp)
Subaccount identifier
Number of results to return (1-1000)
Pagination cursor from a previous response
### Response
```json
{
"$defs": {
"Order": {
"additionalProperties": false,
"description": "An order row (Trade API v2 portfolio order shape).",
"properties": {
"order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Order Id"
},
"user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User Id"
},
"client_order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Client Order Id"
},
"ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ticker"
},
"side": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Side"
},
"action": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Action"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"yes_price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Price"
},
"no_price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "No Price"
},
"yes_price_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Price Dollars"
},
"no_price_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "No Price Dollars"
},
"fill_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Fill Count"
},
"fill_count_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Fill Count Fp"
},
"remaining_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Remaining Count"
},
"remaining_count_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Remaining Count Fp"
},
"initial_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Initial Count"
},
"initial_count_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Initial Count Fp"
},
"taker_fees": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Taker Fees"
},
"maker_fees": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Maker Fees"
},
"taker_fees_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Taker Fees Dollars"
},
"maker_fees_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Maker Fees Dollars"
},
"taker_fill_cost": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Taker Fill Cost"
},
"maker_fill_cost": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Maker Fill Cost"
},
"taker_fill_cost_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Taker Fill Cost Dollars"
},
"maker_fill_cost_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Maker Fill Cost Dollars"
},
"queue_position": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Queue Position"
},
"expiration_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Expiration Time"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created Time"
},
"last_update_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Update Time"
},
"self_trade_prevention_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Trade Prevention Type"
},
"order_group_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Order Group Id"
},
"cancel_order_on_pause": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Cancel Order On Pause"
}
},
"title": "Order",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"orders": {
"items": {
"$ref": "#/$defs/Order"
},
"title": "Orders",
"type": "array"
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cursor"
}
},
"required": [
"success"
],
"title": "GetOrdersOutput",
"type": "object"
}
```
### Parameters
Kalshi API Key ID (provided by the credential system)
Kalshi RSA private key in PEM format (provided by the credential system)
Order ID to retrieve
### Response
```json
{
"$defs": {
"Order": {
"additionalProperties": false,
"description": "An order row (Trade API v2 portfolio order shape).",
"properties": {
"order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Order Id"
},
"user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User Id"
},
"client_order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Client Order Id"
},
"ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ticker"
},
"side": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Side"
},
"action": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Action"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"yes_price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Price"
},
"no_price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "No Price"
},
"yes_price_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Price Dollars"
},
"no_price_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "No Price Dollars"
},
"fill_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Fill Count"
},
"fill_count_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Fill Count Fp"
},
"remaining_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Remaining Count"
},
"remaining_count_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Remaining Count Fp"
},
"initial_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Initial Count"
},
"initial_count_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Initial Count Fp"
},
"taker_fees": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Taker Fees"
},
"maker_fees": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Maker Fees"
},
"taker_fees_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Taker Fees Dollars"
},
"maker_fees_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Maker Fees Dollars"
},
"taker_fill_cost": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Taker Fill Cost"
},
"maker_fill_cost": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Maker Fill Cost"
},
"taker_fill_cost_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Taker Fill Cost Dollars"
},
"maker_fill_cost_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Maker Fill Cost Dollars"
},
"queue_position": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Queue Position"
},
"expiration_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Expiration Time"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created Time"
},
"last_update_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Update Time"
},
"self_trade_prevention_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Trade Prevention Type"
},
"order_group_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Order Group Id"
},
"cancel_order_on_pause": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Cancel Order On Pause"
}
},
"title": "Order",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"order": {
"anyOf": [
{
"$ref": "#/$defs/Order"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetOrderOutput",
"type": "object"
}
```
### Parameters
Market ticker identifier
Number of price levels to return
### Response
```json
{
"$defs": {
"Orderbook": {
"additionalProperties": false,
"properties": {
"yes": {
"items": {
"items": {},
"type": "array"
},
"title": "Yes",
"type": "array"
},
"no": {
"items": {
"items": {},
"type": "array"
},
"title": "No",
"type": "array"
},
"yes_dollars": {
"items": {
"items": {},
"type": "array"
},
"title": "Yes Dollars",
"type": "array"
},
"no_dollars": {
"items": {
"items": {},
"type": "array"
},
"title": "No Dollars",
"type": "array"
}
},
"title": "Orderbook",
"type": "object"
},
"OrderbookFp": {
"additionalProperties": false,
"properties": {
"yes_dollars": {
"items": {
"items": {},
"type": "array"
},
"title": "Yes Dollars",
"type": "array"
},
"no_dollars": {
"items": {
"items": {},
"type": "array"
},
"title": "No Dollars",
"type": "array"
}
},
"title": "OrderbookFp",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"orderbook": {
"anyOf": [
{
"$ref": "#/$defs/Orderbook"
},
{
"type": "null"
}
],
"default": null
},
"orderbook_fp": {
"anyOf": [
{
"$ref": "#/$defs/OrderbookFp"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetOrderbookOutput",
"type": "object"
}
```
### Parameters
Filter by market ticker
Minimum timestamp (Unix seconds)
Maximum timestamp (Unix seconds)
Number of results to return (1-1000)
Pagination cursor from a previous response
### Response
```json
{
"$defs": {
"Trade": {
"additionalProperties": false,
"properties": {
"trade_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Trade Id"
},
"ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ticker"
},
"yes_price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Price"
},
"no_price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "No Price"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"count_fp": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count Fp"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created Time"
},
"taker_side": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Taker Side"
}
},
"title": "Trade",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"trades": {
"items": {
"$ref": "#/$defs/Trade"
},
"title": "Trades",
"type": "array"
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cursor"
}
},
"required": [
"success"
],
"title": "GetTradesOutput",
"type": "object"
}
```
### Parameters
Series ticker identifier
Market ticker identifier
Start timestamp (Unix seconds)
End timestamp (Unix seconds)
Period interval: 1 (minute), 60 (hour), 1440 (day)
### Response
```json
{
"$defs": {
"BidAskDistribution": {
"additionalProperties": false,
"properties": {
"open": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Open"
},
"open_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Open Dollars"
},
"low": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Low"
},
"low_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Low Dollars"
},
"high": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "High"
},
"high_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "High Dollars"
},
"close": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Close"
},
"close_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Close Dollars"
}
},
"title": "BidAskDistribution",
"type": "object"
},
"MarketCandlestick": {
"additionalProperties": false,
"properties": {
"end_period_ts": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "End Period Ts"
},
"yes_bid": {
"anyOf": [
{
"$ref": "#/$defs/BidAskDistribution"
},
{
"type": "null"
}
],
"default": null
},
"yes_ask": {
"anyOf": [
{
"$ref": "#/$defs/BidAskDistribution"
},
{
"type": "null"
}
],
"default": null
},
"price": {
"anyOf": [
{
"$ref": "#/$defs/PriceDistribution"
},
{
"type": "null"
}
],
"default": null
},
"volume": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Volume"
},
"volume_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Volume Fp"
},
"open_interest": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Open Interest"
},
"open_interest_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Open Interest Fp"
}
},
"title": "MarketCandlestick",
"type": "object"
},
"PriceDistribution": {
"additionalProperties": false,
"properties": {
"open": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Open"
},
"open_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Open Dollars"
},
"low": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Low"
},
"low_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Low Dollars"
},
"high": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "High"
},
"high_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "High Dollars"
},
"close": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Close"
},
"close_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Close Dollars"
},
"mean": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Mean"
},
"mean_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mean Dollars"
},
"previous": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Previous"
},
"previous_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Previous Dollars"
},
"min": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Min"
},
"min_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Min Dollars"
},
"max": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Max"
},
"max_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Max Dollars"
}
},
"title": "PriceDistribution",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ticker"
},
"candlesticks": {
"items": {
"$ref": "#/$defs/MarketCandlestick"
},
"title": "Candlesticks",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetCandlesticksOutput",
"type": "object"
}
```
### Parameters
Series ticker identifier
Event ticker identifier
Start timestamp (Unix seconds)
End timestamp (Unix seconds)
Period interval: 1 (minute), 60 (hour), 1440 (day)
### Response
```json
{
"$defs": {
"BidAskDistribution": {
"additionalProperties": false,
"properties": {
"open": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Open"
},
"open_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Open Dollars"
},
"low": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Low"
},
"low_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Low Dollars"
},
"high": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "High"
},
"high_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "High Dollars"
},
"close": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Close"
},
"close_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Close Dollars"
}
},
"title": "BidAskDistribution",
"type": "object"
},
"EventCandlestick": {
"additionalProperties": false,
"properties": {
"end_period_ts": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "End Period Ts"
},
"yes_bid": {
"anyOf": [
{
"$ref": "#/$defs/BidAskDistribution"
},
{
"type": "null"
}
],
"default": null
},
"yes_ask": {
"anyOf": [
{
"$ref": "#/$defs/BidAskDistribution"
},
{
"type": "null"
}
],
"default": null
},
"price": {
"anyOf": [
{
"$ref": "#/$defs/PriceDistribution"
},
{
"type": "null"
}
],
"default": null
},
"volume_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Volume Fp"
},
"open_interest_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Open Interest Fp"
}
},
"title": "EventCandlestick",
"type": "object"
},
"PriceDistribution": {
"additionalProperties": false,
"properties": {
"open": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Open"
},
"open_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Open Dollars"
},
"low": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Low"
},
"low_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Low Dollars"
},
"high": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "High"
},
"high_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "High Dollars"
},
"close": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Close"
},
"close_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Close Dollars"
},
"mean": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Mean"
},
"mean_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mean Dollars"
},
"previous": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Previous"
},
"previous_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Previous Dollars"
},
"min": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Min"
},
"min_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Min Dollars"
},
"max": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Max"
},
"max_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Max Dollars"
}
},
"title": "PriceDistribution",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"market_tickers": {
"items": {
"type": "string"
},
"title": "Market Tickers",
"type": "array"
},
"adjusted_end_ts": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Adjusted End Ts"
},
"market_candlesticks": {
"items": {
"$ref": "#/$defs/EventCandlestick"
},
"title": "Market Candlesticks",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetEventCandlesticksOutput",
"type": "object"
}
```
### Parameters
Kalshi API Key ID (provided by the credential system)
Kalshi RSA private key in PEM format (provided by the credential system)
Filter by market ticker
Filter by order ID
Minimum timestamp (Unix seconds)
Maximum timestamp (Unix seconds)
Subaccount identifier
Number of results to return (1-1000)
Pagination cursor from a previous response
### Response
```json
{
"$defs": {
"Fill": {
"additionalProperties": false,
"properties": {
"fill_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Fill Id"
},
"trade_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Trade Id"
},
"order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Order Id"
},
"client_order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Client Order Id"
},
"ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ticker"
},
"market_ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Market Ticker"
},
"side": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Side"
},
"action": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Action"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"count_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Count Fp"
},
"price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Price"
},
"yes_price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Price"
},
"no_price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "No Price"
},
"yes_price_fixed": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Price Fixed"
},
"no_price_fixed": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "No Price Fixed"
},
"is_taker": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Taker"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created Time"
},
"ts": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Ts"
}
},
"title": "Fill",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"fills": {
"items": {
"$ref": "#/$defs/Fill"
},
"title": "Fills",
"type": "array"
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cursor"
}
},
"required": [
"success"
],
"title": "GetFillsOutput",
"type": "object"
}
```
### Parameters
Kalshi API Key ID (provided by the credential system)
Kalshi RSA private key in PEM format (provided by the credential system)
Filter by market ticker
Filter by event ticker
Min settled timestamp (Unix seconds)
Max settled timestamp (Unix seconds)
Subaccount number (0 primary, 1-63)
Number of results to return (1-1000)
Pagination cursor from a previous response
### Response
```json
{
"$defs": {
"Settlement": {
"additionalProperties": false,
"properties": {
"ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ticker"
},
"event_ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Event Ticker"
},
"market_result": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Market Result"
},
"yes_count_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Count Fp"
},
"yes_total_cost_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Total Cost Dollars"
},
"no_count_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "No Count Fp"
},
"no_total_cost_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "No Total Cost Dollars"
},
"revenue": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Revenue"
},
"settled_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Settled Time"
},
"fee_cost": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Fee Cost"
},
"value": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
}
},
"title": "Settlement",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"settlements": {
"items": {
"$ref": "#/$defs/Settlement"
},
"title": "Settlements",
"type": "array"
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cursor"
}
},
"required": [
"success"
],
"title": "GetSettlementsOutput",
"type": "object"
}
```
### Parameters
Series ticker identifier
Include volume data: "true" or "false"
### Response
```json
{
"$defs": {
"Series": {
"additionalProperties": false,
"properties": {
"ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ticker"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"frequency": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Frequency"
},
"category": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Category"
},
"tags": {
"items": {
"type": "string"
},
"title": "Tags",
"type": "array"
},
"settlement_sources": {
"items": {
"$ref": "#/$defs/SettlementSource"
},
"title": "Settlement Sources",
"type": "array"
},
"contract_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Contract Url"
},
"contract_terms_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Contract Terms Url"
},
"fee_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Fee Type"
},
"fee_multiplier": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Fee Multiplier"
},
"additional_prohibitions": {
"items": {
"type": "string"
},
"title": "Additional Prohibitions",
"type": "array"
},
"product_metadata": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Product Metadata"
},
"volume": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Volume"
},
"volume_fp": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Volume Fp"
},
"last_updated_ts": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Updated Ts"
}
},
"title": "Series",
"type": "object"
},
"SettlementSource": {
"additionalProperties": false,
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
}
},
"title": "SettlementSource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"series": {
"anyOf": [
{
"$ref": "#/$defs/Series"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetSeriesByTickerOutput",
"type": "object"
}
```
### Parameters
Filter by category
Filter by comma-separated tags
Include product metadata: "true" or "false"
Include volume data: "true" or "false"
Min updated timestamp (Unix seconds)
### Response
```json
{
"$defs": {
"Series": {
"additionalProperties": false,
"properties": {
"ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ticker"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"frequency": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Frequency"
},
"category": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Category"
},
"tags": {
"items": {
"type": "string"
},
"title": "Tags",
"type": "array"
},
"settlement_sources": {
"items": {
"$ref": "#/$defs/SettlementSource"
},
"title": "Settlement Sources",
"type": "array"
},
"contract_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Contract Url"
},
"contract_terms_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Contract Terms Url"
},
"fee_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Fee Type"
},
"fee_multiplier": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Fee Multiplier"
},
"additional_prohibitions": {
"items": {
"type": "string"
},
"title": "Additional Prohibitions",
"type": "array"
},
"product_metadata": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Product Metadata"
},
"volume": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Volume"
},
"volume_fp": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Volume Fp"
},
"last_updated_ts": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Updated Ts"
}
},
"title": "Series",
"type": "object"
},
"SettlementSource": {
"additionalProperties": false,
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
}
},
"title": "SettlementSource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"series": {
"items": {
"$ref": "#/$defs/Series"
},
"title": "Series",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetSeriesListOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"exchange_active": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Exchange Active"
},
"trading_active": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Trading Active"
},
"exchange_estimated_resume_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Exchange Estimated Resume Time"
}
},
"required": [
"success"
],
"title": "GetExchangeStatusOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"ExchangeSchedule": {
"additionalProperties": false,
"properties": {
"standard_hours": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Standard Hours",
"type": "array"
},
"maintenance_windows": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Maintenance Windows",
"type": "array"
}
},
"title": "ExchangeSchedule",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"schedule": {
"anyOf": [
{
"$ref": "#/$defs/ExchangeSchedule"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetExchangeScheduleOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"Announcement": {
"additionalProperties": false,
"properties": {
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"delivery_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Delivery Time"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
}
},
"title": "Announcement",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"announcements": {
"items": {
"$ref": "#/$defs/Announcement"
},
"title": "Announcements",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetExchangeAnnouncementsOutput",
"type": "object"
}
```
### Parameters
Kalshi API Key ID (provided by the credential system)
Kalshi RSA private key in PEM format (provided by the credential system)
Market ticker identifier
Order side: "yes" or "no"
Action type: "buy" or "sell"
Number of contracts to trade (provide count or count_fp)
Order type: "limit" or "market" (default "limit")
Yes price in cents (1-99)
No price in cents (1-99)
Yes price in dollars (e.g., '0.56')
No price in dollars (e.g., '0.56')
Custom order identifier
Unix timestamp for order expiration
TIF: fill_or_kill / good_till_canceled / immediate_or_cancel
Maximum cost in cents (auto-enables fill_or_kill)
Maker-only order
Position reduction only
Self-trade prevention: 'taker_at_cross' or 'maker'
Associated order group ID
Count in fixed-point for fractional contracts
Cancel order on market pause
Subaccount to use for the order
### Response
```json
{
"$defs": {
"Order": {
"additionalProperties": false,
"description": "An order row (Trade API v2 portfolio order shape).",
"properties": {
"order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Order Id"
},
"user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User Id"
},
"client_order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Client Order Id"
},
"ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ticker"
},
"side": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Side"
},
"action": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Action"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"yes_price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Price"
},
"no_price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "No Price"
},
"yes_price_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Price Dollars"
},
"no_price_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "No Price Dollars"
},
"fill_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Fill Count"
},
"fill_count_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Fill Count Fp"
},
"remaining_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Remaining Count"
},
"remaining_count_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Remaining Count Fp"
},
"initial_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Initial Count"
},
"initial_count_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Initial Count Fp"
},
"taker_fees": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Taker Fees"
},
"maker_fees": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Maker Fees"
},
"taker_fees_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Taker Fees Dollars"
},
"maker_fees_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Maker Fees Dollars"
},
"taker_fill_cost": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Taker Fill Cost"
},
"maker_fill_cost": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Maker Fill Cost"
},
"taker_fill_cost_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Taker Fill Cost Dollars"
},
"maker_fill_cost_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Maker Fill Cost Dollars"
},
"queue_position": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Queue Position"
},
"expiration_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Expiration Time"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created Time"
},
"last_update_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Update Time"
},
"self_trade_prevention_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Trade Prevention Type"
},
"order_group_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Order Group Id"
},
"cancel_order_on_pause": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Cancel Order On Pause"
}
},
"title": "Order",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"order": {
"anyOf": [
{
"$ref": "#/$defs/Order"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateOrderOutput",
"type": "object"
}
```
### Parameters
Kalshi API Key ID (provided by the credential system)
Kalshi RSA private key in PEM format (provided by the credential system)
Order ID to cancel
### Response
```json
{
"$defs": {
"Order": {
"additionalProperties": false,
"description": "An order row (Trade API v2 portfolio order shape).",
"properties": {
"order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Order Id"
},
"user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User Id"
},
"client_order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Client Order Id"
},
"ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ticker"
},
"side": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Side"
},
"action": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Action"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"yes_price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Price"
},
"no_price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "No Price"
},
"yes_price_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Price Dollars"
},
"no_price_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "No Price Dollars"
},
"fill_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Fill Count"
},
"fill_count_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Fill Count Fp"
},
"remaining_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Remaining Count"
},
"remaining_count_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Remaining Count Fp"
},
"initial_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Initial Count"
},
"initial_count_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Initial Count Fp"
},
"taker_fees": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Taker Fees"
},
"maker_fees": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Maker Fees"
},
"taker_fees_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Taker Fees Dollars"
},
"maker_fees_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Maker Fees Dollars"
},
"taker_fill_cost": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Taker Fill Cost"
},
"maker_fill_cost": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Maker Fill Cost"
},
"taker_fill_cost_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Taker Fill Cost Dollars"
},
"maker_fill_cost_dollars": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Maker Fill Cost Dollars"
},
"queue_position": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Queue Position"
},
"expiration_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Expiration Time"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created Time"
},
"last_update_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Update Time"
},
"self_trade_prevention_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Trade Prevention Type"
},
"order_group_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Order Group Id"
},
"cancel_order_on_pause": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Cancel Order On Pause"
}
},
"title": "Order",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"order": {
"anyOf": [
{
"$ref": "#/$defs/Order"
},
{
"type": "null"
}
],
"default": null
},
"reduced_by": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Reduced By"
},
"reduced_by_fp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Reduced By Fp"
}
},
"required": [
"success"
],
"title": "CancelOrderOutput",
"type": "object"
}
```
### Parameters
Kalshi API Key ID (provided by the credential system)
Kalshi RSA private key in PEM format (provided by the credential system)
Order ID to amend
Market ticker identifier
Order side: "yes" or "no"
Action type: "buy" or "sell"
Original client-specified order ID
New client-specified order ID
Updated quantity for the order
Updated yes price in cents (1-99)
Updated no price in cents (1-99)
Updated yes price in dollars
Updated no price in dollars
Count in fixed-point for fractional contracts
### Response
```json
{
"$defs": {
"AmendedOrder": {
"additionalProperties": false,
"description": "The order shape returned by the amend endpoint (old_order/order).",
"properties": {
"order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Order Id"
},
"user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User Id"
},
"ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ticker"
},
"event_ticker": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Event Ticker"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"side": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Side"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"yes_price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Yes Price"
},
"no_price": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "No Price"
},
"action": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Action"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"remaining_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Remaining Count"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created Time"
},
"expiration_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Expiration Time"
},
"order_group_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Order Group Id"
},
"client_order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Client Order Id"
},
"place_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Place Count"
},
"decrease_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Decrease Count"
},
"queue_position": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Queue Position"
},
"maker_fill_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Maker Fill Count"
},
"taker_fill_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Taker Fill Count"
},
"maker_fees": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Maker Fees"
},
"taker_fees": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Taker Fees"
},
"last_update_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Update Time"
},
"take_profit_order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Take Profit Order Id"
},
"stop_loss_order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Stop Loss Order Id"
},
"amend_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Amend Count"
},
"amend_taker_fill_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Amend Taker Fill Count"
}
},
"title": "AmendedOrder",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"old_order": {
"anyOf": [
{
"$ref": "#/$defs/AmendedOrder"
},
{
"type": "null"
}
],
"default": null
},
"order": {
"anyOf": [
{
"$ref": "#/$defs/AmendedOrder"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "AmendOrderOutput",
"type": "object"
}
```
## Limits & Quotas
- **Base URL**: `https://api.elections.kalshi.com/trade-api/v2`.
- **Pricing**: prices and counts are returned in cents (and as
fixed-point `_fp` / dollar string variants where the API provides
them).
- **Rate limits**: Kalshi enforces per-tier request rate limits; consult
the official docs for current values. Authenticated portfolio and
trading calls are signed per request, so clock skew on the host can
cause signature rejections — keep the system clock in sync.
- **Error model**: non-2xx responses, timeouts, invalid private keys,
and unexpected exceptions are caught and returned as `success=False` +
`error` rather than raising. On failure the data fields stay at their
defaults.
## Related integrations
## Links
- [Kalshi](https://kalshi.com)
---
# Klaviyo Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/klaviyo
Email marketing and automation platform for personalized customer experiences. Manage lists, profiles, and subscriptions for targeted email campaigns.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/klaviyo/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Klaviyo** to any ModuleX agent or workflow. Email-marketing list and profile management against the Klaviyo REST API (`a.klaviyo.com/api`), pinned to revision `2024-10-15`.
**Categories**: Marketing & Advertising · Marketing & Email · Email · Automation · Development · **Auth**: Private API Key · **Actions**: 5
## Authentication
### Private API Key
Authenticate using your Klaviyo Private API Key. Create one in Settings > API Keys
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Klaviyo Private API Key | Your Klaviyo Private API Key for API authentication | Yes | `pk_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX` |
## Available Actions
### Parameters
Field to sort by: 'created', 'id', 'name', or 'updated' (Default: `created`)
Sort direction: 'asc' or 'desc' (Default: `desc`)
Maximum number of lists to return (Default: `100`)
### Response
```json
{
"$defs": {
"KlaviyoList": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"opt_in_process": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Opt In Process"
}
},
"title": "KlaviyoList",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"lists": {
"items": {
"$ref": "#/$defs/KlaviyoList"
},
"title": "Lists",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetListsOutput",
"type": "object"
}
```
### Parameters
The ID of the Klaviyo list to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"opt_in_process": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Opt In Process"
}
},
"required": [
"success"
],
"title": "GetListOutput",
"type": "object"
}
```
### Parameters
The name for the new list
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"opt_in_process": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Opt In Process"
}
},
"required": [
"success"
],
"title": "CreateListOutput",
"type": "object"
}
```
### Parameters
Maximum number of profiles to return (Default: `100`)
Field to sort by: 'created', 'updated', 'email' (Default: `created`)
Sort direction: 'asc' or 'desc' (Default: `desc`)
### Response
```json
{
"$defs": {
"KlaviyoProfile": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Name"
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Name"
},
"phone_number": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Phone Number"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
}
},
"title": "KlaviyoProfile",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"profiles": {
"items": {
"$ref": "#/$defs/KlaviyoProfile"
},
"title": "Profiles",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetProfilesOutput",
"type": "object"
}
```
### Parameters
The ID of the list to add members to
List of profile IDs to add to the list
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"list_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "List Id"
},
"profiles_added": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Profiles Added"
},
"profile_ids": {
"items": {
"type": "string"
},
"title": "Profile Ids",
"type": "array"
},
"extra": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Extra"
}
},
"required": [
"success"
],
"title": "AddMembersToListOutput",
"type": "object"
}
```
## Limits & Quotas
- Pagination follows JSON:API cursor links — both `get_lists` and
`get_profiles` page through results until `max_results` is reached
or `links.next` is exhausted.
- Failures (any non-2xx, plus exceptions) surface as `success=False`
with an `error` string. Empty/blank API keys short-circuit before
the HTTP call.
## Related integrations
## Links
- [Klaviyo](https://www.klaviyo.com)
---
# Lemlist Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/lemlist
Integrate Lemlist into your workflow. Retrieve campaign activities and replies, get lead information, and send emails through the Lemlist inbox.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/lemlist/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Lemlist** to any ModuleX agent or workflow. Manage sales-engagement outreach against the Lemlist REST API (`api.lemlist.com`): retrieve campaign activities and replies, look up lead details, and send emails through the Lemlist inbox.
**Categories**: Sales · Email Marketing · Sales Engagement · **Auth**: API Key · **Actions**: 3
## Authentication
### API Key Authentication
Authenticate using your Lemlist API key
Sign in to Lemlist and open Settings -> Team Settings -> Integrations
Generate an API key (it is shown only once — copy it immediately)
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Lemlist API Key | Your Lemlist API key from Team Settings -> Integrations | Yes | `-` |
## Available Actions
### Parameters
Filter by activity type (e.g., emailOpened, emailClicked, emailReplied, paused)
Filter by campaign ID (e.g., "cam_abc123def456")
Filter by lead ID (e.g., "lea_abc123def456")
Filter for first activity only
Number of results per request (max 100, default 100)
Number of records to skip for pagination (e.g., 0, 100, 200)
### Response
```json
{
"$defs": {
"ActivityItem": {
"additionalProperties": false,
"description": "A single activity row in ``get_activities``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"lead_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lead Id"
},
"campaign_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Campaign Id"
},
"sequence_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sequence Id"
},
"step_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Step Id"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
}
},
"title": "ActivityItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"activities": {
"items": {
"$ref": "#/$defs/ActivityItem"
},
"title": "Activities",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetActivitiesOutput",
"type": "object"
}
```
### Parameters
Lead email address (e.g., "john@example.com") or lead ID (e.g., "lea_abc123def456")
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Name"
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Name"
},
"company_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Name"
},
"job_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Job Title"
},
"company_domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Domain"
},
"is_paused": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Paused"
},
"campaign_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Campaign Id"
},
"contact_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Contact Id"
},
"email_status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Status"
}
},
"required": [
"success"
],
"title": "GetLeadOutput",
"type": "object"
}
```
### Parameters
Identifier for the user sending the message (e.g., "usr_abc123def456")
Email address of the sender (e.g., "sales@company.com")
Mailbox identifier for the sender (e.g., "mbx_abc123def456")
Recipient contact identifier (e.g., "con_abc123def456")
Associated lead identifier (e.g., "lea_abc123def456")
Email subject line
Email message body in HTML format
Array of CC email addresses
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"ok": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Ok"
}
},
"required": [
"success"
],
"title": "SendEmailOutput",
"type": "object"
}
```
## Limits & Quotas
- **Pagination**: `get_activities` accepts `limit` (max 100, default
100) and `offset` for paging through campaign activity.
- **Send eligibility**: `send_email` requires a configured Lemlist
sender user, mailbox, and an existing contact/lead — the values come
from your Lemlist workspace.
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising. Plan for
retries on the agent side based on the error string.
## Related integrations
## Links
- [Lemlist](https://www.lemlist.com)
---
# Lemon Squeezy Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/lemon-squeezy
Digital products and subscriptions platform for selling software, SaaS, and digital goods with built-in payment processing.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/lemon_squeezy/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Lemon Squeezy** to any ModuleX agent or workflow. Read-only access to the Lemon Squeezy v1 REST API (`api.lemonsqueezy.com/v1`): customers, orders, products, subscriptions, and stores.
**Categories**: Finance & Payments · Business Services · Payments · Subscriptions · Digital Products · **Auth**: API Key · **Actions**: 10
## Authentication
### API Key Authentication
Authenticate using your Lemon Squeezy API key
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Lemon Squeezy API Key | Your Lemon Squeezy API key for authentication | Yes | `eyJ...` |
## Available Actions
### Parameters
Page number for pagination (Default: `1`)
Number of results per page (max 100) (Default: `10`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"default": null,
"title": "Data"
},
"meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Meta"
}
},
"required": [
"success"
],
"title": "ListCustomersOutput",
"type": "object"
}
```
### Parameters
The ID of the customer to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"default": null,
"title": "Data"
},
"meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Meta"
}
},
"required": [
"success"
],
"title": "RetrieveCustomerOutput",
"type": "object"
}
```
### Parameters
Page number for pagination (Default: `1`)
Number of results per page (max 100) (Default: `10`)
Filter orders by store ID
Filter orders by user email
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"default": null,
"title": "Data"
},
"meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Meta"
}
},
"required": [
"success"
],
"title": "ListOrdersOutput",
"type": "object"
}
```
### Parameters
The ID of the order to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"default": null,
"title": "Data"
},
"meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Meta"
}
},
"required": [
"success"
],
"title": "RetrieveOrderOutput",
"type": "object"
}
```
### Parameters
Page number for pagination (Default: `1`)
Number of results per page (max 100) (Default: `10`)
Filter products by store ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"default": null,
"title": "Data"
},
"meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Meta"
}
},
"required": [
"success"
],
"title": "ListProductsOutput",
"type": "object"
}
```
### Parameters
The ID of the product to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"default": null,
"title": "Data"
},
"meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Meta"
}
},
"required": [
"success"
],
"title": "RetrieveProductOutput",
"type": "object"
}
```
### Parameters
Page number for pagination (Default: `1`)
Number of results per page (max 100) (Default: `10`)
Filter subscriptions by store ID
Filter by subscription status: on_trial, active, paused, past_due, unpaid, cancelled, expired
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"default": null,
"title": "Data"
},
"meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Meta"
}
},
"required": [
"success"
],
"title": "ListSubscriptionsOutput",
"type": "object"
}
```
### Parameters
The ID of the subscription to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"default": null,
"title": "Data"
},
"meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Meta"
}
},
"required": [
"success"
],
"title": "RetrieveSubscriptionOutput",
"type": "object"
}
```
### Parameters
Page number for pagination (Default: `1`)
Number of results per page (max 100) (Default: `10`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"default": null,
"title": "Data"
},
"meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Meta"
}
},
"required": [
"success"
],
"title": "ListStoresOutput",
"type": "object"
}
```
### Parameters
The ID of the store to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"default": null,
"title": "Data"
},
"meta": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Meta"
}
},
"required": [
"success"
],
"title": "RetrieveStoreOutput",
"type": "object"
}
```
## Limits & Quotas
- Pagination via JSON:API `page[number]` / `page[size]`; `per_page` is
clamped to 100.
- List endpoints return both `data` (array of resources) and `meta`
(pagination block); retrievals return just `data`.
- 404 retrievals return `success=False` with a "not found" message;
other non-200 responses surface the body verbatim.
## Related integrations
## Links
- [Lemon Squeezy](https://lemonsqueezy.com)
---
# Linear Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/linear
Modern project management and issue tracking tool for software teams. Streamline workflows, track bugs, and coordinate tasks with powerful search, filtering, and automation capabilities.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/linear/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Linear** to any ModuleX agent or workflow. Project-management and issue-tracking integration for Linear via the **GraphQL API** at `api.linear.app/graphql`. Covers team discovery, issue CRUD + search, and project list/create.
**Categories**: Project & Task Management · Task Management · Collaboration · **Auth**: OAuth2, API Key · **Actions**: 7
## Authentication
### OAuth2 Authentication
Connect using Linear OAuth (recommended for most use cases)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Linear OAuth application Client ID | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
| Client Secret | Linear OAuth application Client Secret | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://linear.app/oauth/authorize`
- **Token URL**: `https://api.linear.app/oauth/token`
- **Scopes**: `read`, `write`
### API Key Authentication
Authenticate using your Linear API key. Generate one from Linear Settings > API > Personal API keys.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Linear API Key | Your Linear personal API key for authentication | Yes | `lin_api_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
Maximum number of teams to return (Default: `50`)
Cursor for pagination
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"page_info": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Page Info"
},
"teams": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Teams",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetTeamsOutput",
"type": "object"
}
```
### Parameters
The ID of the issue to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"issue": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Issue"
}
},
"required": [
"success"
],
"title": "GetIssueOutput",
"type": "object"
}
```
### Parameters
Filter by team ID
Filter by project ID
Filter by assignee user ID
Filter by workflow state ID
Substring to match in issue titles
Filter by label names
Include archived issues (Default: `false`)
Field to order by ('createdAt' or 'updatedAt') (Default: `updatedAt`)
Maximum number of issues to return (Default: `50`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"page_info": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Page Info"
},
"issues": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Issues",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchIssuesOutput",
"type": "object"
}
```
### Parameters
The team's UUID (the 'id' field returned by get_teams) — NOT the short team key like 'ENG'. Call get_teams first to resolve it.
The title of the issue
Markdown description
UUID of the user to assign the issue to
UUID of the project to add the issue to
UUID of the workflow state
Label UUIDs to attach
Priority level: 0=No priority, 1=Urgent, 2=High, 3=Normal, 4=Low
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"issue": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Issue"
}
},
"required": [
"success"
],
"title": "CreateIssueOutput",
"type": "object"
}
```
### Parameters
The ID of the issue to update
New title
New markdown description
New assignee user ID
Move to a different team
Move to a different project
Change workflow state
Replace labels with these IDs
New priority level (0-4)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"issue": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Issue"
}
},
"required": [
"success"
],
"title": "UpdateIssueOutput",
"type": "object"
}
```
### Parameters
Filter by team ID
Field to order by ('createdAt' or 'updatedAt') (Default: `updatedAt`)
Maximum number of projects to return (Default: `50`)
Cursor for pagination
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"page_info": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Page Info"
},
"projects": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Projects",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListProjectsOutput",
"type": "object"
}
```
### Parameters
The team's UUID (the 'id' field returned by get_teams) — NOT the short team key like 'ENG'. Call get_teams first to resolve it.
The name of the project
The description of the project
The project-status ID
Priority level (0-4)
IDs of users to add as members
Start date (YYYY-MM-DD)
Target date (YYYY-MM-DD)
Label IDs to attach
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"project": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Project"
}
},
"required": [
"success"
],
"title": "CreateProjectOutput",
"type": "object"
}
```
## Limits & Quotas
- All tools share a single GraphQL endpoint; failures (HTTP non-200,
GraphQL `errors`, exceptions) surface as `success=False` + `error`.
- The `search_issues` and `list_projects` actions interpolate filter
values into the GraphQL string verbatim (matching legacy). Inputs
are scoped to internal IDs / label names — not user prose — and
treated as opaque tokens.
- Output objects keep their nested GraphQL shape unchanged (state,
team, assignee, creator, labels.nodes for issues; lead, status for
projects).
## Related integrations
## Links
- [Linear](https://linear.app)
---
# LinkedIn Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/linkedin
LinkedIn social networking platform for professional connections, posts, and organization management
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/linkedin/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **LinkedIn** to any ModuleX agent or workflow. Professional social networking platform for managing posts, comments, likes, profiles, organizations, and ad accounts via the LinkedIn REST API (`api.linkedin.com/rest`).
**Categories**: Social Media · Marketing · Communication · **Auth**: OAuth2 · **Actions**: 18
## Authentication
### OAuth2 Authentication
Connect using LinkedIn OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | LinkedIn OAuth App Client ID | Yes | `-` |
| Client Secret | LinkedIn OAuth App Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://www.linkedin.com/oauth/v2/authorization`
- **Token URL**: `https://www.linkedin.com/oauth/v2/accessToken`
- **Scopes**: `openid`, `profile`, `email`, `w_member_social`
## Available Actions
### Parameters
The share or user generated content post URN where the comment will be made
Entity authoring the comment, must be a person or organization URN (e.g. urn:li:person:ABC123)
Text of the comment
Optional media content entities as a JSON object
URN of the parent comment for nested comments (not available for first-level comments)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateCommentOutput",
"type": "object"
}
```
### Parameters
ID of the organization that will author the post
URL of the image to upload and post
Text to be posted on the LinkedIn timeline
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"post_urn": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Post Urn"
}
},
"required": [
"success"
],
"title": "CreateImagePostOrganizationOutput",
"type": "object"
}
```
### Parameters
URL of the image to upload and post
Text to be posted on the LinkedIn timeline
Visibility restrictions on content. Valid values: CONNECTIONS, PUBLIC, LOGGED_IN
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"post_urn": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Post Urn"
}
},
"required": [
"success"
],
"title": "CreateImagePostUserOutput",
"type": "object"
}
```
### Parameters
The top-level share URN or user generated content URN where the like will be performed
Entity performing the like, must be a person or organization URN
URN of the entity to which the like belongs, should be a sub-entity of the top-level share
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "CreateLikeOnShareOutput",
"type": "object"
}
```
### Parameters
ID of the organization that will author the post
Text to be posted on the LinkedIn timeline
URL of an article to share with the post
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateTextPostOrganizationOutput",
"type": "object"
}
```
### Parameters
Visibility restrictions on content. Valid values: CONNECTIONS, PUBLIC, LOGGED_IN
Text to be posted on the LinkedIn timeline
URL of an article to share with the post
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateTextPostUserOutput",
"type": "object"
}
```
### Parameters
URN of the post to delete (e.g. urn:li:ugcPost:123 or urn:li:share:123)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "DeletePostOutput",
"type": "object"
}
```
### Parameters
ID of the ad account to fetch
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "FetchAdAccountOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetCurrentMemberProfileOutput",
"type": "object"
}
```
### Parameters
Identifier of the person to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetMemberProfileOutput",
"type": "object"
}
```
### Parameters
List of person ID strings to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"results": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Results",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetMultipleMemberProfilesOutput",
"type": "object"
}
```
### Parameters
Limit results to a specific role. Valid values: ADMINISTRATOR, DIRECT_SPONSORED_CONTENT_POSTER, RECRUITING_POSTER, LEAD_CAPTURE_ADMINISTRATOR, LEAD_GEN_FORMS_MANAGER, ANALYST, CURATOR, CONTENT_ADMINISTRATOR
Limit results to a specific role state. Valid values: APPROVED, REJECTED, REQUESTED, REVOKED
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetOrgMemberAccessOutput",
"type": "object"
}
```
### Parameters
ID of the organization for which the access control information is being retrieved
Maximum number of results to return (Default: `50`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"elements": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Elements",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetOrganizationAccessControlOutput",
"type": "object"
}
```
### Parameters
ID of the organization for which administrators are being retrieved
Maximum number of pages to fetch (1-500) (Default: `50`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"elements": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Elements",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetOrganizationAdministratorsOutput",
"type": "object"
}
```
### Parameters
Whether to include the original image data in the response (requires special permissions) (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetProfilePictureFieldsOutput",
"type": "object"
}
```
### Parameters
Parent comment URN to retrieve nested comments for. A composite URN using comment ID and activity URN
Maximum number of results to return (Default: `50`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"elements": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Elements",
"type": "array"
}
},
"required": [
"success"
],
"title": "RetrieveCommentsOnCommentsOutput",
"type": "object"
}
```
### Parameters
URN of the entity to retrieve comments on
Maximum number of results to return (Default: `50`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"elements": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Elements",
"type": "array"
}
},
"required": [
"success"
],
"title": "RetrieveCommentsSharesOutput",
"type": "object"
}
```
### Parameters
Field to search by. Valid values: vanityName, emailDomain
Keyword to search for
Maximum number of results to return (Default: `50`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"elements": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Elements",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchOrganizationOutput",
"type": "object"
}
```
## Limits & Quotas
- LinkedIn API rate limits vary by product and endpoint. Generally 100 requests per day for most marketing/community management endpoints per OAuth app.
- Organization-level posting endpoints are subject to daily limits per organization.
- The `LinkedIn-Version` header is hardcoded to `202509`; LinkedIn periodically deprecates older API versions.
- Non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [LinkedIn](https://www.linkedin.com)
---
# Linkup Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/linkup
Search the web with Linkup — retrieve up-to-date information with source attribution, returning either an AI-generated sourced answer or raw ranked search results.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/linkup/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Linkup** to any ModuleX agent or workflow. Web search for AI agents — retrieve up-to-date information from across the web with source attribution, via the Linkup REST API (`api.linkup.so/v1`).
**Categories**: Web Search & Scraping · Data · Search · **Auth**: API Key · **Actions**: 1
## Authentication
### API Key Authentication
Authenticate using your Linkup API key
Go to https://app.linkup.so and sign up or log in
Open the API Keys section of your dashboard
Create a new API key or copy your existing one
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Linkup API Key | Your Linkup API key from app.linkup.so | Yes | `-` |
## Available Actions
### Parameters
The search query (e.g., "latest AI research papers 2024")
Search depth: "standard" for quick results, "deep" for comprehensive search (also supports "fast") (Default: `standard`)
Output format: "sourcedAnswer" for an AI-generated answer with citations, "searchResults" for raw results, or "structured" (Default: `sourcedAnswer`)
Whether to include images in search results
Add inline citations to answers (only applies when output_type is "sourcedAnswer")
Include sources in the response
Start date for filtering results (YYYY-MM-DD format)
End date for filtering results (YYYY-MM-DD format)
Comma-separated list of domain names to restrict search results to
Comma-separated list of domain names to exclude from search results
### Response
```json
{
"$defs": {
"SearchResultItem": {
"additionalProperties": false,
"description": "A single result row in a ``searchResults`` response.",
"properties": {
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"content": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content"
}
},
"title": "SearchResultItem",
"type": "object"
},
"SearchSource": {
"additionalProperties": false,
"description": "A citation in a ``sourcedAnswer`` response's ``sources`` array.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"snippet": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Snippet"
}
},
"title": "SearchSource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"answer": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Answer"
},
"sources": {
"items": {
"$ref": "#/$defs/SearchSource"
},
"title": "Sources",
"type": "array"
},
"results": {
"items": {
"$ref": "#/$defs/SearchResultItem"
},
"title": "Results",
"type": "array"
},
"structured_data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Structured Data"
}
},
"required": [
"success"
],
"title": "SearchOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limit**: ~60 requests/min.
- **Depth tiers**: `standard` queries are cheaper and faster; `deep`
queries cost more and take longer.
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising. Plan for
retries on the agent side based on the error string.
## Related integrations
## Links
- [Linkup](https://www.linkup.so)
---
# Livestorm Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/livestorm
Video engagement platform for webinars and virtual events
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/livestorm/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Livestorm** to any ModuleX agent or workflow. Video engagement platform for webinars and virtual events via the Livestorm REST API (`api.livestorm.co/v1`).
**Categories**: Scheduling & Events · Marketing · Webinars & Events · **Auth**: API Token · **Actions**: 7
## Authentication
### API Token
Authenticate with a Livestorm private API token (Account Settings -> Integrations -> Public API; account owner/admin, API access must be enabled)
Sign in to Livestorm as the workspace owner or an admin
Open Account Settings -> Integrations and scroll to the 'Public API' card
Generate an API token and copy it (shown only once)
Paste the token into ModuleX (if the Public API card is missing, contact support@livestorm.co to enable API access)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Livestorm API Token | Livestorm private API token, sent as a plain Authorization header (no 'Bearer' prefix) | Yes | `-` |
## Available Actions
### Parameters
The ID of the user who owns the event
The title of the event
The slug of the event
The status of the event: draft, published
The HTML description of the event
Whether the event is recorded
Whether the chat is enabled
Whether everyone can speak
Whether the detailed registration page is enabled
Whether the light registration page is enabled
Whether the recording is public
Whether the event is shown in the company page
Whether the polls are enabled
Whether the questions are enabled
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "CreateEventOutput",
"type": "object"
}
```
### Parameters
The ID of the event
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetEventOutput",
"type": "object"
}
```
### Parameters
The ID of the event
Filter by role: participant, team_member
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Data",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListAttendeesFromEventOutput",
"type": "object"
}
```
### Parameters
Filter events by title
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Data",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListEventsOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Data",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListSessionsOutput",
"type": "object"
}
```
### Parameters
The ID of the session
The referrer of the person registering
The UTM source
The UTM medium
The UTM campaign
The UTM term
The UTM content
Registration fields as key-value pairs where key is the field ID and value is the field value
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "RegisterSomeoneForSessionOutput",
"type": "object"
}
```
### Parameters
The ID of the event
The ID of the user who owns the event
The title of the event
The slug of the event
The status of the event: draft, published
The HTML description of the event
Whether the event is recorded
Whether the chat is enabled
Whether everyone can speak
Whether the detailed registration page is enabled
Whether the light registration page is enabled
Whether the recording is public
Whether the event is shown in the company page
Whether the polls are enabled
Whether the questions are enabled
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "UpdateEventOutput",
"type": "object"
}
```
## Limits & Quotas
- No publicly documented rate limits for the Livestorm API.
- Pagination is applied automatically for list endpoints (page-based).
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Livestorm](https://livestorm.co)
---
# Loops Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/loops
Integrate Loops into the workflow. Create and manage contacts, send transactional emails, and trigger event-based automations.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/loops/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Loops** to any ModuleX agent or workflow. Manage contacts and send emails with Loops. Create and manage contacts, send transactional emails, and trigger event-based automations against the Loops REST API (`app.loops.so/api/v1`).
**Categories**: Marketing & Advertising · Email Marketing · Automation · **Auth**: API Key · **Actions**: 10
## Authentication
### API Key Authentication
Authenticate using your Loops API key
Log in to your Loops account at https://app.loops.so
Go to Settings > API
Create a new API key or copy your existing one
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Loops API Key | Your Loops API key from Settings > API | Yes | `-` |
## Available Actions
### Parameters
The email address for the new contact
The contact first name
The contact last name
Custom source value replacing the default "API"
Whether the contact receives campaign emails (defaults to true)
Group to segment the contact into (one group per contact)
Unique user identifier from your application
Mailing list IDs mapped to boolean values (true to subscribe, false to unsubscribe)
Custom contact properties as key-value pairs (string, number, boolean, or date values)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
}
},
"required": [
"success"
],
"title": "CreateContactOutput",
"type": "object"
}
```
### Parameters
The contact email address (at least one of email or user_id is required)
The contact userId (at least one of email or user_id is required)
The contact first name
The contact last name
Custom source value replacing the default "API"
Whether the contact receives campaign emails (sending true re-subscribes unsubscribed contacts)
Group to segment the contact into (one group per contact)
Mailing list IDs mapped to boolean values (true to subscribe, false to unsubscribe)
Custom contact properties as key-value pairs (send null to reset a property)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
}
},
"required": [
"success"
],
"title": "UpdateContactOutput",
"type": "object"
}
```
### Parameters
The contact email address to search for (at least one of email or user_id is required)
The contact userId to search for (at least one of email or user_id is required)
### Response
```json
{
"$defs": {
"Contact": {
"additionalProperties": false,
"description": "A single contact row in ``find_contact``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Name"
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Name"
},
"source": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Source"
},
"subscribed": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Subscribed"
},
"user_group": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User Group"
},
"user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User Id"
},
"mailing_lists": {
"additionalProperties": true,
"title": "Mailing Lists",
"type": "object"
},
"opt_in_status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Opt In Status"
}
},
"title": "Contact",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"contacts": {
"items": {
"$ref": "#/$defs/Contact"
},
"title": "Contacts",
"type": "array"
}
},
"required": [
"success"
],
"title": "FindContactOutput",
"type": "object"
}
```
### Parameters
The email address of the contact to delete (at least one of email or user_id is required)
The userId of the contact to delete (at least one of email or user_id is required)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "DeleteContactOutput",
"type": "object"
}
```
### Parameters
The email address of the recipient
The ID of the transactional email template to send
Template data variables as key-value pairs (string or number values)
Whether to create the recipient as a contact if they do not already exist (default: false)
Array of file attachments. Each object must have filename (string), contentType (MIME type string), and data (base64-encoded string).
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "SendTransactionalEmailOutput",
"type": "object"
}
```
### Parameters
The name of the event to trigger
The email address of the contact (at least one of email or user_id is required)
The userId of the contact (at least one of email or user_id is required)
Event data as key-value pairs (string, number, boolean, or date values)
Mailing list IDs mapped to boolean values (true to subscribe, false to unsubscribe)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "SendEventOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"MailingList": {
"additionalProperties": false,
"description": "A single mailing list row in ``list_mailing_lists``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"is_public": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Public"
}
},
"title": "MailingList",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"mailing_lists": {
"items": {
"$ref": "#/$defs/MailingList"
},
"title": "Mailing Lists",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListMailingListsOutput",
"type": "object"
}
```
### Parameters
Number of results per page (10-50, default: 20)
Pagination cursor from a previous response to fetch the next page
### Response
```json
{
"$defs": {
"Pagination": {
"additionalProperties": false,
"description": "Pagination block returned by ``list_transactional_emails``.",
"properties": {
"total_results": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Results"
},
"returned_results": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Returned Results"
},
"per_page": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Per Page"
},
"total_pages": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Pages"
},
"next_cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Cursor"
},
"next_page": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Page"
}
},
"title": "Pagination",
"type": "object"
},
"TransactionalEmail": {
"additionalProperties": false,
"description": "A single template row in ``list_transactional_emails``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"last_updated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Updated"
},
"data_variables": {
"items": {
"type": "string"
},
"title": "Data Variables",
"type": "array"
}
},
"title": "TransactionalEmail",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"transactional_emails": {
"items": {
"$ref": "#/$defs/TransactionalEmail"
},
"title": "Transactional Emails",
"type": "array"
},
"pagination": {
"anyOf": [
{
"$ref": "#/$defs/Pagination"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "ListTransactionalEmailsOutput",
"type": "object"
}
```
### Parameters
The property name in camelCase format (e.g., "favoriteColor")
The property data type (e.g., "string", "number", "boolean", "date")
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "CreateContactPropertyOutput",
"type": "object"
}
```
### Parameters
Filter type: "all" for all properties (default) or "custom" for custom properties only
### Response
```json
{
"$defs": {
"ContactProperty": {
"additionalProperties": false,
"description": "A single property row in ``list_contact_properties``.",
"properties": {
"key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Key"
},
"label": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Label"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
}
},
"title": "ContactProperty",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"properties": {
"type": "array",
"items": {
"$ref": "#/$defs/ContactProperty"
},
"title": "Properties"
}
},
"required": [
"success"
],
"title": "ListContactPropertiesOutput",
"type": "object"
}
```
## Limits & Quotas
- Loops applies per-account API rate limits; check your plan in the
Loops dashboard for current values.
- `list_transactional_emails` accepts `per_page` (10-50, default 20)
and a `cursor` for pagination; the response carries a `pagination`
block with `next_cursor`/`next_page` for fetching subsequent pages.
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising. Mutating
endpoints also return HTTP 200 with `{"success": false, "message":
...}` for business-logic failures, which is surfaced as `error`.
## Related integrations
## Links
- [Loops](https://loops.so)
---
# Luma Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/luma
Event management platform for creating, managing, and tracking events and guests
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/luma/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Luma** to any ModuleX agent or workflow. Event management platform for creating, managing, and tracking events and guests via the Luma REST API (`public-api.luma.com/v1`).
**Categories**: Scheduling & Events · Events · Productivity & Collaboration · Marketing · **Auth**: API Key · **Actions**: 8
## Authentication
### API Key Authentication
Authenticate using your Luma API key
Go to https://lu.ma and sign in to your account
Navigate to your calendar settings or developer section
Generate or copy your API key
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Luma API Key | Your Luma API key | Yes | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
## Available Actions
### Parameters
The event name
The event start time as an ISO 8601 datetime, for example 2026-05-15T18:00:00Z
The IANA timezone for the event, for example America/New_York
The event end time as an ISO 8601 datetime
Markdown description for the event
Event visibility: public, members-only, or private
Custom event URL slug
Online meeting URL for a virtual event
Cover image URL uploaded to the Luma CDN
Maximum number of registrations before the event is sold out
Whether guests can register for multiple tickets
Whether approved guests can see who else is attending
Whether to disable default event reminders
How to collect guest names: full-name or first-last
Phone number collection: optional or required
A hex color like #bb2dc7 for the event theme
JSON object with latitude and longitude for the event location
JSON object with address details (type, place_id, description)
JSON array of registration question objects with label and required fields
JSON object with subject and message for the post-event feedback email
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"event": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Event"
}
},
"required": [
"success"
],
"title": "CreateEventOutput",
"type": "object"
}
```
### Parameters
The Luma event ID (usually starts with evt-)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"event": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Event"
}
},
"required": [
"success"
],
"title": "GetEventOutput",
"type": "object"
}
```
### Parameters
Return events starting after this ISO 8601 datetime
Return events starting before this ISO 8601 datetime
The next_cursor value from a previous list response
Number of items to request per page (Default: `50`)
Calendar submission status: approved or pending
Column to sort by (currently only start_at is supported)
Sort order: asc, desc, asc nulls last, or desc nulls last
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"events": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Events",
"type": "array"
},
"has_more": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has More"
},
"next_cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Cursor"
}
},
"required": [
"success"
],
"title": "ListEventsOutput",
"type": "object"
}
```
### Parameters
The Luma event ID (usually starts with evt-)
Guest ID (gst-...), ticket key, guest key (g-...), or email address
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"guest": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Guest"
}
},
"required": [
"success"
],
"title": "GetGuestOutput",
"type": "object"
}
```
### Parameters
The Luma event ID (usually starts with evt-)
Filter by status: approved, session, pending_approval, invited, declined, or waitlist
The next_cursor value from a previous list response
Number of items to request per page (Default: `50`)
Guest field to sort by: name, email, created_at, registered_at, or checked_in_at
Sort order: asc, desc, asc nulls last, or desc nulls last
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"guests": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Guests",
"type": "array"
},
"has_more": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has More"
},
"next_cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Cursor"
}
},
"required": [
"success"
],
"title": "GetGuestsOutput",
"type": "object"
}
```
### Parameters
The Luma event ID (usually starts with evt-)
JSON array of guests, each with at least an email field
JSON object assigning one ticket type to each guest (mutually exclusive with tickets_json)
JSON array assigning multiple tickets to each guest (mutually exclusive with ticket_json)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"guests": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Guests",
"type": "array"
}
},
"required": [
"success"
],
"title": "AddGuestsOutput",
"type": "object"
}
```
### Parameters
The Luma event ID (usually starts with evt-)
Whether to include hidden ticket types (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"ticket_types": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Ticket Types",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListTicketTypesOutput",
"type": "object"
}
```
### Parameters
The Luma event ID (usually starts with evt-)
JSON array of guests to invite, each with at least an email field
Optional invite message (max 200 characters)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "SendInvitesOutput",
"type": "object"
}
```
## Limits & Quotas
- No documented public rate limits; Luma enforces server-side pagination maximums.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Luma](https://luma.com)
---
# Mailchimp Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/mailchimp
Mailchimp marketing platform: list/audience CRUD, subscriber upsert, campaign lifecycle, tags, notes, and segments.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/mailchimp/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Mailchimp** to any ModuleX agent or workflow. Mailchimp marketing platform integration via the v3.0 REST API. Pure HTTP. 19 actions across lists, subscribers, campaigns, tags, notes, and segments.
**Categories**: Marketing & Advertising · Marketing & Email · Email Marketing · CRM · **Auth**: OAuth2, API Key · **Actions**: 19
## Authentication
### OAuth2 Authentication
Connect using Mailchimp OAuth2 (recommended — avoids datacenter discovery and Basic Auth headaches).
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Mailchimp OAuth App Client ID | Yes | `-` |
| Client Secret | Mailchimp OAuth App Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://login.mailchimp.com/oauth2/authorize`
- **Token URL**: `https://login.mailchimp.com/oauth2/token`
### API Key Authentication
Authenticate using your Mailchimp API key. The key includes the datacenter suffix (e.g. xxx-us10).
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Mailchimp API Key | Your Mailchimp API key (with datacenter suffix) | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-us10` |
| Datacenter | Datacenter portion of your API key (suffix after the dash, e.g. 'us10', 'us20', 'eu1'). Mailchimp routes API requests to the datacenter where your account lives. | Yes | `us10` |
## Available Actions
### Parameters
Results (max 1000) (Default: `10`)
Results to skip (Default: `0`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"lists": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Lists",
"type": "array"
},
"total_items": {
"default": 0,
"title": "Total Items",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetListsOutput",
"type": "object"
}
```
### Parameters
The unique list/audience ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"permission_reminder": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Permission Reminder"
},
"contact": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Contact"
},
"campaign_defaults": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Campaign Defaults"
},
"stats": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Stats"
},
"date_created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Date Created"
}
},
"required": [
"success"
],
"title": "GetListOutput",
"type": "object"
}
```
### Parameters
List name
Company name
Street address
City
State/province
Postal code
ISO3166 country code (e.g. 'US')
Permission reminder text
Default from name
Default from email
Default subject line
Default language (Default: `en`)
Allow subscribers to choose HTML or text (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"date_created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Date Created"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "CreateListOutput",
"type": "object"
}
```
### Parameters
The unique list/audience ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"list_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "List Id"
}
},
"required": [
"success"
],
"title": "DeleteListOutput",
"type": "object"
}
```
### Parameters
The unique list/audience ID
Results (max 1000) (Default: `10`)
Results to skip (Default: `0`)
subscribed/unsubscribed/cleaned/pending/transactional/archived
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"members": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Members",
"type": "array"
},
"total_items": {
"default": 0,
"title": "Total Items",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetListMembersOutput",
"type": "object"
}
```
### Parameters
The unique list/audience ID
Subscriber email address
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"email_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Address"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"merge_fields": {
"additionalProperties": true,
"title": "Merge Fields",
"type": "object"
},
"tags": {
"items": {
"type": "string"
},
"title": "Tags",
"type": "array"
},
"vip": {
"default": false,
"title": "Vip",
"type": "boolean"
},
"language": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Language"
},
"timestamp_signup": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp Signup"
},
"last_changed": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Changed"
}
},
"required": [
"success"
],
"title": "GetSubscriberOutput",
"type": "object"
}
```
### Parameters
The unique list/audience ID
Subscriber email address
Status if new (default 'subscribed') (Default: `subscribed`)
Current status
'html' or 'text'
Merge fields (e.g. {'FNAME': 'John'})
Subscriber language
VIP status
Tags to add (active)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"email_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Address"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"merge_fields": {
"additionalProperties": true,
"title": "Merge Fields",
"type": "object"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "AddOrUpdateSubscriberOutput",
"type": "object"
}
```
### Parameters
The unique list/audience ID
Subscriber email address
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"list_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "List Id"
}
},
"required": [
"success"
],
"title": "DeleteSubscriberOutput",
"type": "object"
}
```
### Parameters
Results (max 1000) (Default: `10`)
Results to skip (Default: `0`)
regular/plaintext/absplit/rss/variate
save/paused/schedule/sending/sent
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"campaigns": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Campaigns",
"type": "array"
},
"total_items": {
"default": 0,
"title": "Total Items",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetCampaignsOutput",
"type": "object"
}
```
### Parameters
Campaign ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "GetCampaignOutput",
"type": "object"
}
```
### Parameters
Campaign type (Default: `regular`)
The unique list/audience ID
Subject line
From name
Reply-to email
Campaign title
Preview text
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "CreateCampaignOutput",
"type": "object"
}
```
### Parameters
Campaign ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"campaign_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Campaign Id"
}
},
"required": [
"success"
],
"title": "DeleteCampaignOutput",
"type": "object"
}
```
### Parameters
Campaign ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"campaign_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Campaign Id"
}
},
"required": [
"success"
],
"title": "SendCampaignOutput",
"type": "object"
}
```
### Parameters
Campaign ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "GetCampaignReportOutput",
"type": "object"
}
```
### Parameters
The unique list/audience ID
Subscriber email address
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"tags": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Tags",
"type": "array"
},
"total_items": {
"default": 0,
"title": "Total Items",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetMemberTagsOutput",
"type": "object"
}
```
### Parameters
The unique list/audience ID
Subscriber email address
List of {name, status} where status is 'active' or 'inactive'
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
}
},
"required": [
"success"
],
"title": "UpdateMemberTagsOutput",
"type": "object"
}
```
### Parameters
The unique list/audience ID
Subscriber email address
Note content
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"note": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Note"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
}
},
"required": [
"success"
],
"title": "AddNoteToSubscriberOutput",
"type": "object"
}
```
### Parameters
The unique list/audience ID
Results (max 1000) (Default: `10`)
Results to skip (Default: `0`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"segments": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Segments",
"type": "array"
},
"total_items": {
"default": 0,
"title": "Total Items",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetSegmentsOutput",
"type": "object"
}
```
### Parameters
The unique list/audience ID
Segment ID
Subscriber email address
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"segment_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Segment Id"
}
},
"required": [
"success"
],
"title": "AddMemberToSegmentOutput",
"type": "object"
}
```
## Related integrations
## Links
- [Mailchimp](https://mailchimp.com)
---
# Mailgun Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/mailgun
Transactional email API for sending, receiving, and tracking email
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/mailgun/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Mailgun** to any ModuleX agent or workflow. Transactional email API integration for sending, receiving, and tracking email via the Mailgun REST API (`api.mailgun.net`).
**Categories**: Communication · Email · **Auth**: Mailgun API Key · **Actions**: 9
## Authentication
### Mailgun API Key
Authenticate using your Mailgun API key and region
Log in to https://app.mailgun.com
Go to Settings > API Security
Copy your Private API key
Set MAILGUN_REGION to 'EU' if your account is on the EU infrastructure, otherwise leave as 'US'
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Mailgun API Key | Private API key from Mailgun dashboard (Settings > API Security) | Yes | `key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
| Mailgun Region | API region: 'US' (default) or 'EU' | No | `US` |
## Available Actions
### Parameters
Mailgun domain name to send from
Sender display name
Sender email address
Recipient email address(es) as a list of strings
Email subject line
Plain text message body
HTML message body
Reply-to email address
Enable Mailgun test mode (message accepted but not delivered) (Default: `true`)
Enable or disable DKIM signatures on the message (Default: `true`)
Enable or disable tracking on the message (Default: `true`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "SendEmailOutput",
"type": "object"
}
```
### Parameters
Email address to verify
### Response
```json
{
"$defs": {
"EmailVerificationResult": {
"additionalProperties": false,
"properties": {
"address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Address"
},
"did_you_mean": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Did You Mean"
},
"is_disposable_address": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Disposable Address"
},
"is_role_address": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Role Address"
},
"reason": {
"items": {
"type": "string"
},
"title": "Reason",
"type": "array"
},
"result": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
},
"risk": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Risk"
}
},
"title": "EmailVerificationResult",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"verification": {
"anyOf": [
{
"$ref": "#/$defs/EmailVerificationResult"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "VerifyEmailOutput",
"type": "object"
}
```
### Parameters
Mailing list address (e.g. list@yourdomain.com)
Email address of the member to add
Display name of the member
Extra arbitrary member data as a JSON object
Subscription status: 'yes' (default) or 'no' for unsubscribed (Default: `yes`)
If 'yes', update existing member; if 'no', error on duplicate. Values: yes, no (Default: `no`)
### Response
```json
{
"$defs": {
"MailinglistMember": {
"additionalProperties": false,
"properties": {
"address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Address"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"subscribed": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Subscribed"
},
"vars": {
"anyOf": [
{
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Vars"
}
},
"title": "MailinglistMember",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"member": {
"anyOf": [
{
"$ref": "#/$defs/MailinglistMember"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateMailinglistMemberOutput",
"type": "object"
}
```
### Parameters
Route priority (lower numbers are evaluated first)
Human-readable description of the route
Mailgun route filter expression, e.g. match_recipient('.*@example.com')
List of route action strings, e.g. ['forward("dest@example.com")', 'stop()']
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"route_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Route Id"
},
"route_message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Route Message"
}
},
"required": [
"success"
],
"title": "CreateRouteOutput",
"type": "object"
}
```
### Parameters
Mailing list address (e.g. list@yourdomain.com)
Email address of the member to remove
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"member_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Member Address"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "DeleteMailinglistMemberOutput",
"type": "object"
}
```
### Parameters
Filter by domain state: active, unverified, disabled (Default: `active`)
### Response
```json
{
"$defs": {
"DomainSummary": {
"additionalProperties": false,
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"smtp_login": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Smtp Login"
},
"web_prefix": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web Prefix"
}
},
"title": "DomainSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"domains": {
"items": {
"$ref": "#/$defs/DomainSummary"
},
"title": "Domains",
"type": "array"
},
"total_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Count"
}
},
"required": [
"success"
],
"title": "ListDomainsOutput",
"type": "object"
}
```
### Parameters
Mailing list address (e.g. list@yourdomain.com)
Filter by subscription: 'true' for subscribed only, 'false' for unsubscribed only, or omit for all
### Response
```json
{
"$defs": {
"MailinglistMember": {
"additionalProperties": false,
"properties": {
"address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Address"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"subscribed": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Subscribed"
},
"vars": {
"anyOf": [
{
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Vars"
}
},
"title": "MailinglistMember",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"members": {
"items": {
"$ref": "#/$defs/MailinglistMember"
},
"title": "Members",
"type": "array"
},
"total_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Count"
}
},
"required": [
"success"
],
"title": "ListMailinglistMembersOutput",
"type": "object"
}
```
### Parameters
Mailing list address (e.g. list@yourdomain.com)
Email address of the member to retrieve
### Response
```json
{
"$defs": {
"MailinglistMember": {
"additionalProperties": false,
"properties": {
"address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Address"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"subscribed": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Subscribed"
},
"vars": {
"anyOf": [
{
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Vars"
}
},
"title": "MailinglistMember",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"member": {
"anyOf": [
{
"$ref": "#/$defs/MailinglistMember"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "RetrieveMailinglistMemberOutput",
"type": "object"
}
```
### Parameters
Mailgun domain name
Email address to suppress
Suppression list category: bounces, unsubscribes, or complaints
Bounce error code (only for 'bounces' category) (Default: `550`)
Bounce error message (only for 'bounces' category)
Tag to unsubscribe from (only for 'unsubscribes' category). Use '*' for all. (Default: `*`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "SuppressEmailOutput",
"type": "object"
}
```
## Limits & Quotas
- **Free tier**: 100 emails/day for the first 30 days (sandbox domain).
- **Paid plans**: rate limits vary by plan; see https://www.mailgun.com/pricing/.
- **Email validation**: billed separately per validation request.
- **Error model**: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Mailgun](https://www.mailgun.com)
---
# Mem0 Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/mem0
Persistent agent memory management — add, search, and retrieve long-term memories so AI agents can recall user context, preferences, and prior conversations across sessions.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/mem0/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Mem0** to any ModuleX agent or workflow. Persistent agent memory management against the Mem0 REST API (`api.mem0.ai`) — add, search, and retrieve long-term memories so AI agents can recall user context, preferences, and prior conversations across sessions.
**Categories**: AI & Machine Learning · Knowledge Base · Agentic · **Auth**: API Key · **Actions**: 3
## Authentication
### API Key Authentication
Authenticate using your Mem0 API key
Go to https://app.mem0.ai and sign up or log in
Open the dashboard and navigate to the 'API Keys' section
Create a new API key or copy your existing one
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Mem0 API Key | Your Mem0 API key from app.mem0.ai | Yes | `-` |
## Available Actions
### Parameters
User ID associated with the memory (e.g., "user_123", "alice@example.com")
Array of message objects with role and content (e.g., [{"role": "user", "content": "Hello"}])
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"event_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Event Id"
}
},
"required": [
"success"
],
"title": "AddMemoriesOutput",
"type": "object"
}
```
### Parameters
User ID to search memories for (e.g., "user_123", "alice@example.com")
Search query to find relevant memories (e.g., "What are my favorite foods?")
Maximum number of results to return (e.g., 10, 50, 100) (Default: `10`)
### Response
```json
{
"$defs": {
"SearchResultRecord": {
"additionalProperties": false,
"description": "A single ranked result returned by ``search_memories``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"memory": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Memory"
},
"user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User Id"
},
"agent_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Agent Id"
},
"app_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "App Id"
},
"run_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Run Id"
},
"hash": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hash"
},
"metadata": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Metadata"
},
"categories": {
"items": {
"type": "string"
},
"title": "Categories",
"type": "array"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"score": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Score"
}
},
"title": "SearchResultRecord",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"search_results": {
"items": {
"$ref": "#/$defs/SearchResultRecord"
},
"title": "Search Results",
"type": "array"
},
"ids": {
"items": {
"type": "string"
},
"title": "Ids",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchMemoriesOutput",
"type": "object"
}
```
### Parameters
User ID to retrieve memories for (e.g., "user_123", "alice@example.com")
Specific memory ID to retrieve (e.g., "mem_abc123")
Start date for filtering by created_at (e.g., "2024-01-15")
End date for filtering by created_at (e.g., "2024-12-31")
Maximum number of results to return (e.g., 10, 50, 100) (Default: `10`)
Page number to retrieve for paginated list results (Default: `1`)
### Response
```json
{
"$defs": {
"MemoryRecord": {
"additionalProperties": false,
"description": "A single memory object returned by ``get_memories``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"memory": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Memory"
},
"user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User Id"
},
"agent_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Agent Id"
},
"app_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "App Id"
},
"run_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Run Id"
},
"hash": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Hash"
},
"metadata": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Metadata"
},
"categories": {
"items": {
"type": "string"
},
"title": "Categories",
"type": "array"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"title": "MemoryRecord",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"memories": {
"items": {
"$ref": "#/$defs/MemoryRecord"
},
"title": "Memories",
"type": "array"
},
"ids": {
"items": {
"type": "string"
},
"title": "Ids",
"type": "array"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"next": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next"
},
"previous": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Previous"
}
},
"required": [
"success"
],
"title": "GetMemoriesOutput",
"type": "object"
}
```
## Limits & Quotas
- Rate limits and quotas depend on your Mem0 plan; see
https://docs.mem0.ai for current tiers.
- `add_memories` is processed asynchronously — the response returns a
`status` (initially `PENDING`) and an `event_id` for polling progress,
not the stored memory records themselves.
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising. Plan for
retries on the agent side based on the error string.
## Related integrations
## Links
- [Mem0](https://mem0.ai)
---
# Mercury Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/mercury
Business banking platform for startups and scaling companies
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/mercury/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Mercury** to any ModuleX agent or workflow. Business banking platform for startups and scaling companies. Integrates with the Mercury REST API (`backend.mercury.com/api/v1`).
**Categories**: Finance · Banking · **Auth**: API Token · **Actions**: 1
## Authentication
### API Token
Use your Mercury API token to authenticate
Log in to your Mercury dashboard at https://app.mercury.com
Navigate to Settings -> API Tokens
Generate a new API token and copy it
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| API Token | Your Mercury API token from the dashboard | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
The unique ID of the Mercury account to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"account_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Account Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"account_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Account Type"
},
"current_balance": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Current Balance"
},
"available_balance": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Available Balance"
},
"routing_number": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Routing Number"
},
"account_number": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Account Number"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
}
},
"required": [
"success"
],
"title": "GetAccountInfoOutput",
"type": "object"
}
```
## Limits & Quotas
- No publicly documented rate limits for the Mercury API.
- Access is limited to accounts with API access enabled by Mercury support.
- Error model: non-2xx responses and timeouts are caught and returned as
`success=False` + `error` rather than raising.
## Related integrations
## Links
- [Mercury](https://mercury.com)
---
# Microsoft 365 People Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/microsoft-365-people
Manage contacts and contact folders via the Microsoft Graph API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/microsoft_365_people/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Microsoft 365 People** to any ModuleX agent or workflow. Manage contacts and contact folders via the Microsoft Graph API (`graph.microsoft.com/v1.0`).
**Categories**: Productivity & Collaboration · Contacts · **Auth**: OAuth2 · **Actions**: 3
## Authentication
### OAuth2 Authentication
Connect using Microsoft OAuth2 (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Microsoft Azure AD OAuth App Client ID | Yes | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
| Client Secret | Microsoft Azure AD OAuth App Client Secret | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/authorize`
- **Token URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/token`
- **Scopes**: `Contacts.ReadWrite`, `User.Read`, `offline_access`
## Available Actions
### Parameters
Email address of the contact
First name of the contact
Last name of the contact
ID of the contact folder to create the contact in (defaults to the root contacts folder)
Mobile phone number of the contact
List of home phone numbers for the contact (each element is a string)
Street address of the contact
City of the contact
State of the contact
Postal code of the contact
Country or region of the contact
### Response
```json
{
"$defs": {
"ContactOutput": {
"additionalProperties": false,
"description": "A Microsoft 365 contact resource.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"given_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Given Name"
},
"surname": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Surname"
},
"email_addresses": {
"items": {
"$ref": "#/$defs/EmailAddress"
},
"title": "Email Addresses",
"type": "array"
},
"mobile_phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mobile Phone"
},
"home_phones": {
"items": {
"type": "string"
},
"title": "Home Phones",
"type": "array"
},
"home_address": {
"anyOf": [
{
"$ref": "#/$defs/HomeAddress"
},
{
"type": "null"
}
],
"default": null
},
"created_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created Date Time"
},
"last_modified_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Modified Date Time"
}
},
"title": "ContactOutput",
"type": "object"
},
"EmailAddress": {
"additionalProperties": false,
"description": "An email address entry on a contact.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Address"
}
},
"title": "EmailAddress",
"type": "object"
},
"HomeAddress": {
"additionalProperties": false,
"description": "A physical address on a contact.",
"properties": {
"street": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Street"
},
"city": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "City"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"postal_code": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Postal Code"
},
"country_or_region": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Country Or Region"
}
},
"title": "HomeAddress",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"contact": {
"anyOf": [
{
"$ref": "#/$defs/ContactOutput"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateContactOutput",
"type": "object"
}
```
### Parameters
The display name of the new contact folder
### Response
```json
{
"$defs": {
"ContactFolderOutput": {
"additionalProperties": false,
"description": "A Microsoft 365 contact folder resource.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"parent_folder_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Parent Folder Id"
}
},
"title": "ContactFolderOutput",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"folder": {
"anyOf": [
{
"$ref": "#/$defs/ContactFolderOutput"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateContactFolderOutput",
"type": "object"
}
```
### Parameters
ID of the contact to update
ID of the contact folder containing the contact (defaults to the root contacts folder)
New email address for the contact
New first name for the contact
New last name for the contact
New mobile phone number for the contact
New list of home phone numbers for the contact (each element is a string)
New street address for the contact
New city for the contact
New state for the contact
New postal code for the contact
New country or region for the contact
### Response
```json
{
"$defs": {
"ContactOutput": {
"additionalProperties": false,
"description": "A Microsoft 365 contact resource.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"given_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Given Name"
},
"surname": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Surname"
},
"email_addresses": {
"items": {
"$ref": "#/$defs/EmailAddress"
},
"title": "Email Addresses",
"type": "array"
},
"mobile_phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mobile Phone"
},
"home_phones": {
"items": {
"type": "string"
},
"title": "Home Phones",
"type": "array"
},
"home_address": {
"anyOf": [
{
"$ref": "#/$defs/HomeAddress"
},
{
"type": "null"
}
],
"default": null
},
"created_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created Date Time"
},
"last_modified_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Modified Date Time"
}
},
"title": "ContactOutput",
"type": "object"
},
"EmailAddress": {
"additionalProperties": false,
"description": "An email address entry on a contact.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Address"
}
},
"title": "EmailAddress",
"type": "object"
},
"HomeAddress": {
"additionalProperties": false,
"description": "A physical address on a contact.",
"properties": {
"street": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Street"
},
"city": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "City"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"postal_code": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Postal Code"
},
"country_or_region": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Country Or Region"
}
},
"title": "HomeAddress",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"contact": {
"anyOf": [
{
"$ref": "#/$defs/ContactOutput"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UpdateContactOutput",
"type": "object"
}
```
## Limits & Quotas
- Microsoft Graph API throttling: 10,000 requests per 10 minutes per app per tenant.
- Per-mailbox limits: 4 concurrent connections.
- Error model: non-2xx responses raise `httpx.HTTPStatusError` (Pattern A).
## Related integrations
## Links
- [Microsoft 365 People](https://www.microsoft.com/en-us/microsoft-365)
---
# Microsoft Bookings Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/microsoft-bookings
Create and manage Microsoft Bookings businesses, services, staff members, customers, and appointments via the Microsoft Graph API.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/microsoft_bookings/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Microsoft Bookings** to any ModuleX agent or workflow. Create and manage Microsoft Bookings businesses, services, staff members, customers, and appointments through the Microsoft Graph API (`graph.microsoft.com/v1.0`).
**Categories**: Scheduling & Events · Productivity & Collaboration · Scheduling · Business Services · **Auth**: OAuth2 · **Actions**: 10
## Authentication
### OAuth2 Authentication
Connect using a Microsoft (Azure AD / Entra ID) OAuth app with Bookings scopes.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Application (client) ID of the Azure AD app registration. | Yes | `00000000-0000-0000-0000-000000000000` |
| Client Secret | Client secret value from the Azure AD app registration. | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/authorize`
- **Token URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/token`
- **Scopes**: `offline_access`, `Bookings.Read.All`, `BookingsAppointment.ReadWrite.All`, `Bookings.ReadWrite.All`, `Bookings.Manage.All`
## Available Actions
### Parameters
ID of the Microsoft Bookings business that owns the appointment.
ID of the appointment to cancel.
Message sent to the customer and staff members explaining the cancellation.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "CancelAppointmentOutput",
"type": "object"
}
```
### Parameters
ID of the Microsoft Bookings business that will own the appointment.
ID of the booking service the customer is booking.
ID of the existing customer the appointment is being booked for.
Appointment start time in ISO 8601 format (e.g. 2024-05-01T12:00:00).
Appointment end time in ISO 8601 format (e.g. 2024-05-01T13:00:00).
IANA time zone for the appointment (e.g. UTC, America/Chicago).
Display name to record for the customer on this appointment.
SMTP email address for the customer on this appointment.
IANA time zone for the customer (falls back to time_zone if omitted).
Phone number to record for the customer on this appointment.
Notes from the customer associated with this appointment.
True indicates that the appointment will be held online.
List of staff member IDs assigned to this appointment.
If True, send SMS notifications to the customer for the appointment.
Regular monetary price for the appointment.
Pricing structure: undefined, fixedPrice, startingAt, hourly, free, priceVaries, callUs, notSet.
Appointment length in ISO 8601 duration (e.g. PT1H, PT30M).
Maximum number of customers allowed in this appointment.
Time to reserve before the appointment in ISO 8601 duration (e.g. PT15M).
Time to reserve after the appointment in ISO 8601 duration (e.g. PT15M).
Notes from the staff member about this appointment.
Additional information sent to the customer when the appointment is confirmed.
True allows the customer to manage bookings created by the staff.
If True, the customer will not receive an email confirmation for this appointment.
### Response
```json
{
"$defs": {
"AppointmentSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"self_service_appointment_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Service Appointment Id"
},
"service_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Service Id"
},
"service_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Service Name"
},
"customer_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Customer Name"
},
"customer_email_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Customer Email Address"
},
"customer_time_zone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Customer Time Zone"
},
"start_date_time": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Start Date Time"
},
"end_date_time": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "End Date Time"
},
"duration": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Duration"
},
"price": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Price"
},
"price_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Price Type"
},
"is_location_online": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Location Online"
},
"join_web_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Join Web Url"
},
"sms_notifications_enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Sms Notifications Enabled"
},
"staff_member_ids": {
"items": {
"type": "string"
},
"title": "Staff Member Ids",
"type": "array"
},
"customers": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Customers",
"type": "array"
}
},
"title": "AppointmentSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"appointment": {
"anyOf": [
{
"$ref": "#/$defs/AppointmentSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateAppointmentOutput",
"type": "object"
}
```
### Parameters
Customer-facing name of the booking business.
Email address for the business.
Telephone number for the business.
URL of the business web site.
Street address of the business.
City of the business.
State of the business.
Postal code of the business.
Country or region of the business.
ISO currency code the business operates in (e.g. USD).
Free-form description of the type of business.
### Response
```json
{
"$defs": {
"BusinessSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Phone"
},
"web_site_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web Site Url"
},
"default_currency_iso": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Default Currency Iso"
},
"business_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Business Type"
},
"address": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Address"
},
"is_published": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Published"
},
"public_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Public Url"
}
},
"title": "BusinessSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"business": {
"anyOf": [
{
"$ref": "#/$defs/BusinessSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateBusinessOutput",
"type": "object"
}
```
### Parameters
ID of the Microsoft Bookings business that will own the customer.
Customer's full name.
Customer's email address.
Customer's phone number.
Type of phone number: home, business, mobile. (Default: `home`)
Street address for the customer.
City for the customer.
State for the customer.
Postal code for the customer.
Country or region for the customer.
### Response
```json
{
"$defs": {
"CustomerSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"email_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Address"
},
"phones": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Phones",
"type": "array"
},
"addresses": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Addresses",
"type": "array"
}
},
"title": "CustomerSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"customer": {
"anyOf": [
{
"$ref": "#/$defs/CustomerSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateCustomerOutput",
"type": "object"
}
```
### Parameters
ID of the Microsoft Bookings business that will own the service.
Customer-facing name of the service.
Default service length in ISO 8601 duration (e.g. PT1H30M).
Free-form description for the service.
Default monetary price for the service.
Default pricing structure: undefined, fixedPrice, startingAt, hourly, free, priceVaries, callUs, notSet.
True indicates the service will be held online.
List of staff member IDs allowed to provide this service.
True hides this service from the customer-facing booking page.
Additional notes about this service (staff-facing).
True enables SMS notifications to customers for this service.
### Response
```json
{
"$defs": {
"ServiceSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"default_duration": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Default Duration"
},
"default_price": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Default Price"
},
"default_price_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Default Price Type"
},
"is_location_online": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Location Online"
},
"is_hidden_from_customers": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Hidden From Customers"
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Notes"
},
"staff_member_ids": {
"items": {
"type": "string"
},
"title": "Staff Member Ids",
"type": "array"
},
"sms_notifications_enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Sms Notifications Enabled"
}
},
"title": "ServiceSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"service": {
"anyOf": [
{
"$ref": "#/$defs/ServiceSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateServiceOutput",
"type": "object"
}
```
### Parameters
ID of the Microsoft Bookings business that will own the staff member.
Staff member's name as shown to customers.
Staff member's email address.
Staff member's role: guest, administrator, viewer, externalGuest, scheduler, teamMember.
IANA time zone for the staff member (e.g. America/Chicago).
True means the staff member follows the business' default hours; False uses workingHours.
True to send email notifications to this staff member.
### Response
```json
{
"$defs": {
"StaffMemberSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"email_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Address"
},
"role": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Role"
},
"time_zone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Time Zone"
},
"use_business_hours": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Use Business Hours"
},
"is_email_notification_enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Email Notification Enabled"
},
"availability_is_affected_by_personal_calendar": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Availability Is Affected By Personal Calendar"
}
},
"title": "StaffMemberSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"staff_member": {
"anyOf": [
{
"$ref": "#/$defs/StaffMemberSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateStaffMemberOutput",
"type": "object"
}
```
### Parameters
ID of the Microsoft Bookings business to query.
Calendar view start in ISO 8601 (e.g. 2024-05-01T00:00:00Z).
Calendar view end in ISO 8601 (e.g. 2024-05-31T23:59:59Z).
### Response
```json
{
"$defs": {
"AppointmentSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"self_service_appointment_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Self Service Appointment Id"
},
"service_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Service Id"
},
"service_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Service Name"
},
"customer_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Customer Name"
},
"customer_email_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Customer Email Address"
},
"customer_time_zone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Customer Time Zone"
},
"start_date_time": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Start Date Time"
},
"end_date_time": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "End Date Time"
},
"duration": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Duration"
},
"price": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Price"
},
"price_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Price Type"
},
"is_location_online": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Location Online"
},
"join_web_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Join Web Url"
},
"sms_notifications_enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Sms Notifications Enabled"
},
"staff_member_ids": {
"items": {
"type": "string"
},
"title": "Staff Member Ids",
"type": "array"
},
"customers": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Customers",
"type": "array"
}
},
"title": "AppointmentSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"appointments": {
"items": {
"$ref": "#/$defs/AppointmentSummary"
},
"title": "Appointments",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListAppointmentsOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"BusinessSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Phone"
},
"web_site_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web Site Url"
},
"default_currency_iso": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Default Currency Iso"
},
"business_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Business Type"
},
"address": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Address"
},
"is_published": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Published"
},
"public_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Public Url"
}
},
"title": "BusinessSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"businesses": {
"items": {
"$ref": "#/$defs/BusinessSummary"
},
"title": "Businesses",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListBusinessesOutput",
"type": "object"
}
```
### Parameters
ID of the Microsoft Bookings business to query.
### Response
```json
{
"$defs": {
"ServiceSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"default_duration": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Default Duration"
},
"default_price": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Default Price"
},
"default_price_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Default Price Type"
},
"is_location_online": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Location Online"
},
"is_hidden_from_customers": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Hidden From Customers"
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Notes"
},
"staff_member_ids": {
"items": {
"type": "string"
},
"title": "Staff Member Ids",
"type": "array"
},
"sms_notifications_enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Sms Notifications Enabled"
}
},
"title": "ServiceSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"services": {
"items": {
"$ref": "#/$defs/ServiceSummary"
},
"title": "Services",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListServicesOutput",
"type": "object"
}
```
### Parameters
ID of the Microsoft Bookings business to query.
### Response
```json
{
"$defs": {
"StaffMemberSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"email_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email Address"
},
"role": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Role"
},
"time_zone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Time Zone"
},
"use_business_hours": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Use Business Hours"
},
"is_email_notification_enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Email Notification Enabled"
},
"availability_is_affected_by_personal_calendar": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Availability Is Affected By Personal Calendar"
}
},
"title": "StaffMemberSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"staff_members": {
"items": {
"$ref": "#/$defs/StaffMemberSummary"
},
"title": "Staff Members",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListStaffMembersOutput",
"type": "object"
}
```
## Limits & Quotas
- Microsoft Graph enforces a per-app and per-user throttling envelope; Bookings endpoints typically allow a few thousand requests per 10-minute window per app+tenant. See the [Microsoft Graph throttling guidance](https://learn.microsoft.com/en-us/graph/throttling) for current limits.
- Creating appointments requires that the referenced `customer_id` already exists in the business; the tool will surface the underlying Graph error if it does not.
- **Error model**: non-2xx Graph responses and timeouts are caught and returned as `success=False` + `error` rather than raising. Plan for retries on the agent side based on the error string.
- Dynamic ID dropdowns (business/staff/service/customer/appointment pickers) are not part of this integration; the LLM must supply IDs directly. Use the `list_*` tools to enumerate available IDs first.
## Related integrations
## Links
- [Microsoft Bookings](https://www.microsoft.com/en-us/microsoft-365/business/scheduling-and-booking-app)
---
# Microsoft Dynamics 365 Sales Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/microsoft-dynamics-365-sales
CRM platform for managing accounts, contacts, appointments, and custom entities via the Dynamics 365 Web API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/microsoft_dynamics_365_sales/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Microsoft Dynamics 365 Sales** to any ModuleX agent or workflow. CRM platform integration for managing accounts, contacts, appointments, and custom entities via the Dynamics 365 Web API (`https://{org}.crm.dynamics.com/api/data/v9.2`).
**Categories**: CRM · Sales · Productivity & Collaboration · **Auth**: OAuth2 · **Actions**: 11
## Authentication
### OAuth2 Authentication
Connect using Microsoft OAuth2 (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Microsoft Entra (Azure AD) OAuth App Client ID | Yes | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
| Client Secret | Microsoft Entra (Azure AD) OAuth App Client Secret | Yes | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
| Dynamics 365 Instance URL | Your Dynamics 365 org URL hostname (e.g. org12345.crm.dynamics.com) | Yes | `org12345.crm.dynamics.com` |
#### OAuth Configuration
- **Authorization URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/authorize`
- **Token URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/token`
- **Scopes**: `https://dynamics.microsoft.com/user_impersonation`, `offline_access`
## Available Actions
### Parameters
Title of the appointment
Start date/time in ISO 8601 format (e.g. 2026-02-20T12:00:00Z)
End date/time in ISO 8601 format
Account ID the appointment is regarding
Email address of the Dynamics system user to add as attendee
Optional category value (numeric). Use list_appointment_categories to discover valid values
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"appointment_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Appointment Id"
},
"deep_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Deep Link"
},
"appointment": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Appointment"
}
},
"required": [
"success"
],
"title": "CreateAppointmentOutput",
"type": "object"
}
```
### Parameters
Identifier of the solution to associate the entity with
Display name for the new entity (e.g. 'Bank Account')
Primary name attribute of the new entity (e.g. 'Account Name')
Language code (e.g. 1033 for English US) (Default: `1033`)
Array of attribute definition objects to add to the entity
Description of the new entity
Whether the entity supports activities (Default: `false`)
Whether the entity supports notes (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"entity": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Entity"
}
},
"required": [
"success"
],
"title": "CreateCustomEntityOutput",
"type": "object"
}
```
### Parameters
Contact GUID to look up directly
Find contacts whose full name contains this value
Custom OData $filter expression (e.g. "lastname eq 'Smith'")
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"contacts": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Contacts",
"type": "array"
}
},
"required": [
"success"
],
"title": "FindContactOutput",
"type": "object"
}
```
### Parameters
Account GUID to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"account": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Account"
}
},
"required": [
"success"
],
"title": "GetAccountOutput",
"type": "object"
}
```
### Parameters
Optional OData $filter (e.g. 'statecode eq 0' for active accounts)
Number of records per page (max 5000) (Default: `50`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"accounts": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Accounts",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListAccountsOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"category_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Category Type"
},
"categories": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Categories",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListAppointmentCategoriesOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"options": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Options",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListAppointmentCategoryOptionsOutput",
"type": "object"
}
```
### Parameters
Optional OData $filter (e.g. 'statecode eq 0')
Number of appointments to return (max 100) (Default: `25`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"appointments": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Appointments",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListAppointmentsOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"solutions": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Solutions",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListSolutionIdOptionsOutput",
"type": "object"
}
```
### Parameters
Substring to match against account name
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"accounts": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Accounts",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchAccountsOutput",
"type": "object"
}
```
### Parameters
Appointment activity GUID to update
Updated subject/title
Updated start in ISO 8601
Updated end in ISO 8601
Updated category value (numeric). Use list_appointment_categories to discover valid values
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"appointment_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Appointment Id"
},
"updated_fields": {
"items": {
"type": "string"
},
"title": "Updated Fields",
"type": "array"
}
},
"required": [
"success"
],
"title": "UpdateAppointmentOutput",
"type": "object"
}
```
## Limits & Quotas
- **API limits**: Dynamics 365 enforces per-org service protection limits (typically 6,000 requests per 5-minute sliding window per user).
- **Throttling**: Returns HTTP 429 when limits are exceeded; retry after the `Retry-After` header value.
- **Error model**: Non-2xx responses are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Microsoft Dynamics 365 Sales](https://dynamics.microsoft.com)
---
# Microsoft Entra ID Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/microsoft-entra-id
Identity and access management via Microsoft Graph API for users, groups, and directory objects.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/microsoft_entra_id/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Microsoft Entra ID** to any ModuleX agent or workflow. Identity and access management via the Microsoft Graph API (`graph.microsoft.com/v1.0`) for managing users, groups, and directory objects in Microsoft Entra ID (formerly Azure Active Directory).
**Categories**: Developer Tools & Infrastructure · Identity & Access Management · Enterprise · Security · **Auth**: OAuth2 · **Actions**: 12
## Authentication
### OAuth2 Authentication
Connect using Microsoft Entra ID OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Microsoft Entra ID OAuth App Client ID | Yes | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
| Client Secret | Microsoft Entra ID OAuth App Client Secret | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/authorize`
- **Token URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/token`
- **Scopes**: `User.Read`, `User.ReadWrite.All`, `Group.ReadWrite.All`, `GroupMember.ReadWrite.All`, `Directory.ReadWrite.All`
## Available Actions
### Parameters
Identifier of the group
Identifier of the user to add
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "AddMemberToGroupOutput",
"type": "object"
}
```
### Parameters
The name to display in the address book for the group
Set to true for mail-enabled groups
The mail alias for the group, unique for groups in the organization. Maximum length is 64 characters.
Set to true for security-enabled groups
### Response
```json
{
"$defs": {
"GroupSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"mail_enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Mail Enabled"
},
"mail_nickname": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mail Nickname"
},
"security_enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Security Enabled"
},
"group_types": {
"items": {
"type": "string"
},
"title": "Group Types",
"type": "array"
},
"deleted_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted Date Time"
}
},
"title": "GroupSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"group": {
"anyOf": [
{
"$ref": "#/$defs/GroupSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateGroupOutput",
"type": "object"
}
```
### Parameters
Identifier of the group to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "DeleteGroupOutput",
"type": "object"
}
```
### Parameters
Identifier of the user. Leave empty to use the signed-in user.
### Response
```json
{
"$defs": {
"ManagerInfo": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"job_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Job Title"
},
"mobile_phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mobile Phone"
}
},
"title": "ManagerInfo",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"manager": {
"anyOf": [
{
"$ref": "#/$defs/ManagerInfo"
},
{
"type": "null"
}
],
"default": null
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "GetManagerOutput",
"type": "object"
}
```
### Parameters
Identifier of the user. Leave empty to use the signed-in user.
### Response
```json
{
"$defs": {
"GroupSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"mail_enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Mail Enabled"
},
"mail_nickname": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mail Nickname"
},
"security_enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Security Enabled"
},
"group_types": {
"items": {
"type": "string"
},
"title": "Group Types",
"type": "array"
},
"deleted_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted Date Time"
}
},
"title": "GroupSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"groups": {
"items": {
"$ref": "#/$defs/GroupSummary"
},
"title": "Groups",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetMs365GroupsOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"GroupSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"mail_enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Mail Enabled"
},
"mail_nickname": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mail Nickname"
},
"security_enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Security Enabled"
},
"group_types": {
"items": {
"type": "string"
},
"title": "Group Types",
"type": "array"
},
"deleted_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted Date Time"
}
},
"title": "GroupSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"groups": {
"items": {
"$ref": "#/$defs/GroupSummary"
},
"title": "Groups",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetOrganizationGroupsOutput",
"type": "object"
}
```
### Parameters
Maximum number of users to return. Omit for no limit.
OData filter expression, e.g. 'accountEnabled eq true' (Default: `accountEnabled eq true`)
OData search expression, e.g. '"displayName:John"'
### Response
```json
{
"$defs": {
"UserSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"full_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Full Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"user_principal_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User Principal Name"
},
"surname": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Surname"
},
"given_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Given Name"
},
"job_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Job Title"
},
"mobile_phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mobile Phone"
}
},
"title": "UserSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"users": {
"items": {
"$ref": "#/$defs/UserSummary"
},
"title": "Users",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetOrganizationUsersOutput",
"type": "object"
}
```
### Parameters
Identifier of the user. Leave empty to use the signed-in user.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetProfileOutput",
"type": "object"
}
```
### Parameters
Identifier of the group
Identifier of the user to remove
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "RemoveMemberFromGroupOutput",
"type": "object"
}
```
### Parameters
Keywords to search by
The maximum number of groups to return (Default: `100`)
### Response
```json
{
"$defs": {
"GroupSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"display_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Display Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"mail_enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Mail Enabled"
},
"mail_nickname": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mail Nickname"
},
"security_enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Security Enabled"
},
"group_types": {
"items": {
"type": "string"
},
"title": "Group Types",
"type": "array"
},
"deleted_date_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted Date Time"
}
},
"title": "GroupSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"groups": {
"items": {
"$ref": "#/$defs/GroupSummary"
},
"title": "Groups",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchGroupsOutput",
"type": "object"
}
```
### Parameters
Identifier of the group to update
Whether people external to the organization can send messages to the group
Whether new members added to the group will be auto-subscribed to receive email notifications
An optional description for the group
The name to display in the address book for the group
The mail alias for the group. Maximum length is 64 characters.
Set to true for security-enabled groups
Specifies the visibility of the group. Allowed values: Public, Private.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "UpdateGroupOutput",
"type": "object"
}
```
### Parameters
Identifier of the user to update
The name to display in the address book for the user
The SMTP address for the user
The mail alias for the user
Whether the account is enabled (Default: `true`)
The street address of the user's place of business
The city in which the user is located
The state or province in the user's address
The postal code for the user's postal address
The country/region in which the user is located
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "UpdateUserOutput",
"type": "object"
}
```
## Limits & Quotas
- **Microsoft Graph throttling**: Varies by resource and tenant; typically 10,000 requests per 10 minutes per app per tenant for most directory endpoints.
- **Pagination**: List endpoints may return paginated results; the integration follows `@odata.nextLink` automatically.
- **Error model**: Non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Microsoft Entra ID](https://entra.microsoft.com)
---
# Microsoft Excel Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/microsoft-excel
Read, write, and manage Excel workbooks stored in OneDrive via the Microsoft Graph API.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/microsoft_excel/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Microsoft Excel** to any ModuleX agent or workflow. Read, write, and manage Excel workbooks stored in OneDrive via the Microsoft Graph REST API (`graph.microsoft.com/v1.0`).
**Categories**: Productivity & Collaboration · Spreadsheets · **Auth**: Microsoft OAuth 2.0 · **Actions**: 9
## Authentication
### Microsoft OAuth 2.0
Connect to Microsoft Excel via Microsoft Identity Platform OAuth (recommended). Requires consent to access OneDrive files.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Microsoft Entra ID (Azure AD) application Client ID. | Yes | `00000000-0000-0000-0000-000000000000` |
| Client Secret | Microsoft Entra ID application Client Secret value. | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/authorize`
- **Token URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/token`
- **Scopes**: `Files.ReadWrite`, `User.Read`, `offline_access`
## Available Actions
### Parameters
Drive item ID of the workbook (the spreadsheet file) in OneDrive.
Two-dimensional array of unformatted row values, e.g. [[1, 2, 3], [4, 5, 6]]. Each inner array is one row.
ID of the workbook table to append to. Provide either table_id or table_name.
Name of the workbook table (set in the Table Design tab). Used when table_id is not available, e.g. for personal accounts.
### Response
```json
{
"$defs": {
"TableRow": {
"additionalProperties": false,
"description": "One Microsoft Graph workbookTableRow returned by table operations.",
"properties": {
"index": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Index"
},
"values": {
"items": {
"items": {},
"type": "array"
},
"title": "Values",
"type": "array"
}
},
"title": "TableRow",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"row": {
"anyOf": [
{
"$ref": "#/$defs/TableRow"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "AddAWorksheetTablerowOutput",
"type": "object"
}
```
### Parameters
Drive item ID of the workbook in OneDrive.
Name of the worksheet to append the row to.
Array of cell values for the new row, e.g. [1, 2, 3]. Each item is one cell.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Address"
},
"values": {
"items": {
"items": {},
"type": "array"
},
"title": "Values",
"type": "array"
}
},
"required": [
"success"
],
"title": "AddRowOutput",
"type": "object"
}
```
### Parameters
Drive item ID of the workbook in OneDrive.
Name of the worksheet to search.
Column letter to search, e.g. 'A'.
Value to search for. Numeric strings will also be matched as numbers.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"found": {
"default": false,
"title": "Found",
"type": "boolean"
},
"row_number": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Row Number"
},
"address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Address"
},
"values": {
"items": {
"items": {},
"type": "array"
},
"title": "Values",
"type": "array"
},
"column_values": {
"items": {},
"title": "Column Values",
"type": "array"
}
},
"required": [
"success"
],
"title": "FindRowOutput",
"type": "object"
}
```
### Parameters
Drive item ID of the workbook in OneDrive.
Name of the worksheet to read.
Array of column letters to retrieve, e.g. ['A', 'C'].
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"values": {
"additionalProperties": {
"items": {},
"type": "array"
},
"title": "Values",
"type": "object"
}
},
"required": [
"success"
],
"title": "GetColumnsOutput",
"type": "object"
}
```
### Parameters
Drive item ID of the workbook in OneDrive.
Name of the worksheet to read.
Range within the worksheet, e.g. 'A1:C4'. If omitted, the entire used range is returned.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Address"
},
"row_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Row Count"
},
"column_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Column Count"
},
"values": {
"items": {
"items": {},
"type": "array"
},
"title": "Values",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetSpreadsheetOutput",
"type": "object"
}
```
### Parameters
Drive item ID of the workbook in OneDrive.
ID of the workbook table whose rows you want.
### Response
```json
{
"$defs": {
"TableRow": {
"additionalProperties": false,
"description": "One Microsoft Graph workbookTableRow returned by table operations.",
"properties": {
"index": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Index"
},
"values": {
"items": {
"items": {},
"type": "array"
},
"title": "Values",
"type": "array"
}
},
"title": "TableRow",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"rows": {
"items": {
"$ref": "#/$defs/TableRow"
},
"title": "Rows",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetTableRowsOutput",
"type": "object"
}
```
### Parameters
Maximum number of batch pages to fetch (1-500). Default 50.
### Response
```json
{
"$defs": {
"FolderOption": {
"additionalProperties": false,
"description": "One folder option returned by list_folder_id_options.",
"properties": {
"value": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
},
"label": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Label"
}
},
"title": "FolderOption",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"options": {
"items": {
"$ref": "#/$defs/FolderOption"
},
"title": "Options",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListFolderIdOptionsOutput",
"type": "object"
}
```
### Parameters
Drive item ID of the workbook in OneDrive.
Name of the worksheet containing the cell.
Cell address to update, e.g. 'A1'.
Value to write to the cell.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Address"
},
"values": {
"items": {
"items": {},
"type": "array"
},
"title": "Values",
"type": "array"
}
},
"required": [
"success"
],
"title": "UpdateCellOutput",
"type": "object"
}
```
### Parameters
Drive item ID of the workbook in OneDrive.
ID of the workbook table.
Zero-based index of the row to update.
Array of cell values for the updated row, e.g. [1, 2, 3]. Each item is one cell.
### Response
```json
{
"$defs": {
"TableRow": {
"additionalProperties": false,
"description": "One Microsoft Graph workbookTableRow returned by table operations.",
"properties": {
"index": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Index"
},
"values": {
"items": {
"items": {},
"type": "array"
},
"title": "Values",
"type": "array"
}
},
"title": "TableRow",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"row": {
"anyOf": [
{
"$ref": "#/$defs/TableRow"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UpdateWorksheetTablerowOutput",
"type": "object"
}
```
## Limits & Quotas
- **Microsoft Graph throttling**: Graph applies per-app and per-user
throttling. Excessive requests return HTTP `429` with a
`Retry-After` header. See
https://learn.microsoft.com/en-us/graph/throttling for current
limits.
- **Workbook session limits**: Excel workbook APIs apply additional
per-workbook session throttling; consider batching writes via
`add_a_worksheet_tablerow` rather than per-cell `update_cell` calls
when possible.
- **Table updates** (`update_worksheet_tablerow`): work or school
Microsoft accounts only. Personal accounts cannot enumerate or
update workbook tables.
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising. Plan for
retries on the agent side based on the error string.
## Related integrations
## Links
- [Microsoft Excel](https://www.microsoft.com/en-us/microsoft-365/excel)
---
# Microsoft OneDrive Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/microsoft-onedrive
Access and manage files in Microsoft OneDrive: search, list, upload, download, create folders, and create sharing links via the Microsoft Graph API.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/microsoft_onedrive/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Microsoft OneDrive** to any ModuleX agent or workflow. Access and manage files in Microsoft OneDrive through the Microsoft Graph API (`https://graph.microsoft.com/v1.0`) — search, list, upload, download files, create folders, and produce sharing links using a user's delegated permissions.
**Categories**: Cloud Infrastructure · File Storage · Productivity · **Auth**: OAuth2 · **Actions**: 11
## Authentication
### OAuth2 Authentication
Connect using Microsoft (Azure Entra) OAuth
Go to https://entra.microsoft.com -> App registrations -> New registration
Set supported account types according to your needs (commonly 'Accounts in any organizational directory and personal Microsoft accounts')
Add redirect URI (Web): https://api.modulex.dev/credentials/oauth2/callback
Under API permissions, add Microsoft Graph delegated permissions: Files.ReadWrite.All, Sites.ReadWrite.All, User.Read, offline_access
Create a client secret under Certificates & secrets
Copy Application (client) ID and the client secret value
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Microsoft (Azure Entra) App Client ID | Yes | `00000000-0000-0000-0000-000000000000` |
| Client Secret | Microsoft (Azure Entra) App Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/authorize`
- **Token URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/token`
- **Scopes**: `Files.ReadWrite.All`, `Sites.ReadWrite.All`, `User.Read`, `offline_access`
## Available Actions
### Parameters
The name of the new folder to be created (e.g. 'New Folder').
The ID of the folder which the new folder should be created within. Omit to create the folder at the drive root.
Reference of the shared folder which the new folder should be created in (e.g. '/drives/{driveId}/items/{folderId}/children'). Mutually exclusive with parent_folder_id.
### Response
```json
{
"$defs": {
"CreateFolderResult": {
"additionalProperties": false,
"description": "Microsoft Graph response for creating a folder.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"webUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Weburl"
},
"parentReference": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Parentreference"
}
},
"title": "CreateFolderResult",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"$ref": "#/$defs/CreateFolderResult"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateFolderOutput",
"type": "object"
}
```
### Parameters
The ID of the DriveItem to create a sharing link for.
The type of sharing link to create. One of: view, edit, embed.
The scope of link to create. One of: anonymous, organization.
### Response
```json
{
"$defs": {
"CreateLinkResult": {
"additionalProperties": false,
"description": "Microsoft Graph response for creating a sharing link (Permission resource).",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"link": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Link"
}
},
"title": "CreateLinkResult",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"$ref": "#/$defs/CreateLinkResult"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateLinkOutput",
"type": "object"
}
```
### Parameters
The ID of the file to download. Provide either file_id or file_path.
The path to the file from the root folder (e.g. 'Documents/My Subfolder/File 1.docx'). Provide either file_id or file_path.
The file name to save the downloaded content as, under /tmp. Include the file extension.
Optional format to convert the file to. One of: pdf, html.
### Response
```json
{
"$defs": {
"DownloadFileResult": {
"additionalProperties": false,
"description": "Result envelope for download_file — file saved to /tmp + base64 content.",
"properties": {
"tmp_file_path": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Tmp File Path"
},
"file_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "File Name"
},
"size_bytes": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size Bytes"
},
"content_base64": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Base64"
}
},
"title": "DownloadFileResult",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"$ref": "#/$defs/DownloadFileResult"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "DownloadFileOutput",
"type": "object"
}
```
### Parameters
The name of the file or folder to search for.
Set to true to return only files in the response. Defaults to false. (Default: `false`)
### Response
```json
{
"$defs": {
"DriveItemSummary": {
"additionalProperties": false,
"description": "A DriveItem (file or folder) as returned by Microsoft Graph.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"webUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Weburl"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"createdDateTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Createddatetime"
},
"lastModifiedDateTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lastmodifieddatetime"
},
"file": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "File"
},
"folder": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Folder"
},
"parentReference": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Parentreference"
}
},
"title": "DriveItemSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"items": {
"items": {
"$ref": "#/$defs/DriveItemSummary"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "FindFileByNameOutput",
"type": "object"
}
```
### Parameters
The ID of the Excel (.xlsx) file in OneDrive.
Name of the table as set in the Table Design tab of Excel.
By default, the headers are included as the first row. Set true to remove them. (Default: `false`)
Number of rows to return. Leave at 0 to return all rows. (Default: `0`)
### Response
```json
{
"$defs": {
"GetExcelTableResult": {
"additionalProperties": false,
"description": "Result envelope for get_excel_table — table rows as list[list[str]].",
"properties": {
"rows": {
"items": {
"items": {
"type": "string"
},
"type": "array"
},
"title": "Rows",
"type": "array"
},
"row_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Row Count"
}
},
"title": "GetExcelTableResult",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"$ref": "#/$defs/GetExcelTableResult"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetExcelTableOutput",
"type": "object"
}
```
### Parameters
The ID of the DriveItem to retrieve.
### Response
```json
{
"$defs": {
"DriveItemSummary": {
"additionalProperties": false,
"description": "A DriveItem (file or folder) as returned by Microsoft Graph.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"webUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Weburl"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"createdDateTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Createddatetime"
},
"lastModifiedDateTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lastmodifieddatetime"
},
"file": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "File"
},
"folder": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Folder"
},
"parentReference": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Parentreference"
}
},
"title": "DriveItemSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"item": {
"anyOf": [
{
"$ref": "#/$defs/DriveItemSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetFileByIdOutput",
"type": "object"
}
```
### Parameters
The ID of the folder whose children should be listed.
Set true to return only files (omit subfolders). (Default: `false`)
### Response
```json
{
"$defs": {
"DriveItemSummary": {
"additionalProperties": false,
"description": "A DriveItem (file or folder) as returned by Microsoft Graph.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"webUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Weburl"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"createdDateTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Createddatetime"
},
"lastModifiedDateTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lastmodifieddatetime"
},
"file": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "File"
},
"folder": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Folder"
},
"parentReference": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Parentreference"
}
},
"title": "DriveItemSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"items": {
"items": {
"$ref": "#/$defs/DriveItemSummary"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListFilesInFolderOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"DriveSummary": {
"additionalProperties": false,
"description": "A Drive object as returned by Microsoft Graph.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"driveType": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Drivetype"
},
"owner": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Owner"
},
"quota": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Quota"
}
},
"title": "DriveSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"drives": {
"items": {
"$ref": "#/$defs/DriveSummary"
},
"title": "Drives",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListMyDrivesOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"SharedFolderReferenceOption": {
"additionalProperties": false,
"description": "A {label, value} option usable as create_folder.shared_folder_reference.",
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Label"
},
"value": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
}
},
"title": "SharedFolderReferenceOption",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"options": {
"items": {
"$ref": "#/$defs/SharedFolderReferenceOption"
},
"title": "Options",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListSharedFolderReferenceOptionsOutput",
"type": "object"
}
```
### Parameters
The query text used to search for items. Values may be matched across several fields including filename, metadata, and file content.
Set true to filter out folders from the results. (Default: `false`)
### Response
```json
{
"$defs": {
"DriveItemSummary": {
"additionalProperties": false,
"description": "A DriveItem (file or folder) as returned by Microsoft Graph.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"webUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Weburl"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"createdDateTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Createddatetime"
},
"lastModifiedDateTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lastmodifieddatetime"
},
"file": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "File"
},
"folder": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Folder"
},
"parentReference": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Parentreference"
}
},
"title": "DriveItemSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"items": {
"items": {
"$ref": "#/$defs/DriveItemSummary"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchFilesOutput",
"type": "object"
}
```
### Parameters
The ID of the folder where you want to upload the file.
Publicly accessible URL of the file to upload. The integration downloads the content and re-uploads it to OneDrive.
Name of the new uploaded file (including extension).
### Response
```json
{
"$defs": {
"UploadFileResult": {
"additionalProperties": false,
"description": "Microsoft Graph response for an uploaded DriveItem (subset of fields).",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"webUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Weburl"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
}
},
"title": "UploadFileResult",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"$ref": "#/$defs/UploadFileResult"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UploadFileOutput",
"type": "object"
}
```
## Limits & Quotas
- Microsoft Graph applies per-app and per-user throttling — bursty workloads
may receive `429` responses with `Retry-After` hints. See
https://learn.microsoft.com/en-us/graph/throttling for current limits.
- `download_file` saves the file under the backend's `/tmp` directory **and**
returns the content base64-encoded. For very large files, prefer routing
through the workflow-engine layer.
- `upload_file` accepts only a publicly-accessible source URL. Uploading from
a local `/tmp` path is not supported.
- Dynamic dropdowns for folder, file, drive, and table selection are not
exposed — supply IDs and names directly. Use `list_my_drives`,
`list_files_in_folder`, `search_files`, or `find_file_by_name` to discover
IDs.
- Webhook-style notifications (new file / new folder created) are not exposed
in this integration; route those needs to the workflow-engine layer.
- **Error model**: non-2xx responses, timeouts, and unexpected exceptions are
caught and returned as `success=False` + `error` rather than raising. Agents
should branch on the error string to decide whether to retry or surface to
the user.
## Related integrations
## Links
- [Microsoft OneDrive](https://onedrive.live.com)
---
# Microsoft Outlook Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/microsoft-outlook
Send, draft, search, and organize email; manage contacts, folders, and categories in Microsoft Outlook via Microsoft Graph.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/microsoft_outlook/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Microsoft Outlook** to any ModuleX agent or workflow. Send, draft, search, and organize email; manage contacts, folders, and categories in Microsoft Outlook via Microsoft Graph (`graph.microsoft.com/v1.0`). Uses delegated permissions on behalf of an authenticated Microsoft 365 user.
**Categories**: Communication · Email · Productivity · Communication · Microsoft · **Auth**: OAuth2 · **Actions**: 20
## Authentication
### OAuth2 Authentication
Connect with your Microsoft account using OAuth 2.0 against the Microsoft identity platform.
Register an application at https://entra.microsoft.com (Azure AD > App registrations)
Under 'Authentication', add the redirect URI: https://api.modulex.dev/credentials/oauth2/callback
Under 'API permissions', add Microsoft Graph delegated permissions: Mail.ReadWrite, Mail.Send, MailboxSettings.Read, Contacts.ReadWrite, User.Read, User.ReadBasic.All, offline_access
Under 'Certificates & secrets', create a new client secret
Copy the Application (client) ID and the client secret into ModuleX
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Microsoft Entra Application (client) ID for the Microsoft Graph app. | Yes | `00000000-0000-0000-0000-000000000000` |
| Client Secret | Microsoft Entra client secret for the Microsoft Graph app. | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/authorize`
- **Token URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/token`
- **Scopes**: `offline_access`, `User.Read`, `User.ReadBasic.All`, `Mail.ReadWrite`, `Mail.Send`, `MailboxSettings.Read`, `Contacts.ReadWrite`
## Available Actions
### Parameters
The identifier of the message to update.
The name of the label/category to add.
The User ID of a shared mailbox. If not provided, defaults to the authenticated user's mailbox.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"categories": {
"items": {
"type": "string"
},
"title": "Categories",
"type": "array"
}
},
"required": [
"success"
],
"title": "AddLabelToEmailOutput",
"type": "object"
}
```
### Parameters
Array of recipient email addresses.
Subject of the approval email.
URL the recipient clicks to approve / resume the workflow.
URL the recipient clicks to cancel the workflow.
The User ID of a shared mailbox. If not provided, defaults to the authenticated user's mailbox.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"sent": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Sent"
}
},
"required": [
"success"
],
"title": "ApproveWorkflowOutput",
"type": "object"
}
```
### Parameters
Given name of the contact.
Surname of the contact.
Email addresses for the contact (list of strings).
Array of phone numbers (list of strings).
Additional contact details to merge into the request body. See https://docs.microsoft.com/en-us/graph/api/resources/contact
### Response
```json
{
"$defs": {
"ContactSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"displayName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Displayname"
},
"givenName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Givenname"
},
"surname": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Surname"
},
"emailAddresses": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Emailaddresses",
"type": "array"
},
"businessPhones": {
"items": {
"type": "string"
},
"title": "Businessphones",
"type": "array"
}
},
"title": "ContactSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"contact": {
"anyOf": [
{
"$ref": "#/$defs/ContactSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateContactOutput",
"type": "object"
}
```
### Parameters
Array of TO recipient email addresses (list of strings).
Array of CC recipient email addresses (list of strings).
Array of BCC recipient email addresses (list of strings).
Subject of the email.
Content type of the body. Valid values: text, html. (Default: `text`)
Body content of the email in text or HTML.
Array of file URLs to fetch and attach to the message (list of strings).
Additional Message resource fields merged into the request. See https://docs.microsoft.com/en-us/graph/api/resources/message
The User ID of a shared mailbox. If not provided, defaults to the authenticated user's mailbox.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"isDraft": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Isdraft"
},
"webLink": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Weblink"
}
},
"required": [
"success"
],
"title": "CreateDraftEmailOutput",
"type": "object"
}
```
### Parameters
The identifier of the message to reply to.
Content of the reply in text format.
Array of TO recipient email addresses to override on the draft (list of strings).
Array of CC recipient email addresses (list of strings).
Array of BCC recipient email addresses (list of strings).
Subject override for the reply.
Array of file URLs to attach to the reply (list of strings).
Additional Message resource fields merged into the message body.
The User ID of a shared mailbox.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"isDraft": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Isdraft"
}
},
"required": [
"success"
],
"title": "CreateDraftReplyOutput",
"type": "object"
}
```
### Parameters
The identifier of the message containing the attachment.
The identifier of the attachment to download.
The User ID of a shared mailbox.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"content_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Type"
},
"size": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"content_bytes_base64": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content Bytes Base64"
}
},
"required": [
"success"
],
"title": "DownloadAttachmentOutput",
"type": "object"
}
```
### Parameters
Provide email address, given name, surname, or display name (case sensitive).
The maximum number of results to return. (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"contacts": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Contacts",
"type": "array"
}
},
"required": [
"success"
],
"title": "FindContactsOutput",
"type": "object"
}
```
### Parameters
Search query. Can use property syntax like "to:example@example.com" or "subject:example". Not for use with filter or order_by.
OData $filter expression, e.g. contains(subject, 'meet for lunch?'). Not for use with search.
OData $orderby expression, e.g. receivedDateTime desc. Not for use with search.
Maximum number of messages to return. (Default: `100`)
If true, expands attachments on each returned message. (Default: `false`)
Comma-separated message property names to return (e.g. id,subject,from,receivedDateTime). Shrinks payload size.
The User ID of a shared mailbox.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"messages": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Messages",
"type": "array"
}
},
"required": [
"success"
],
"title": "FindEmailOutput",
"type": "object"
}
```
### Parameters
The user ID owning the shared folder.
The ID of the shared folder to search.
Search query. Not for use with filter or order_by.
OData $filter expression.
OData $orderby expression.
Maximum number of messages to return. (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"messages": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Messages",
"type": "array"
}
},
"required": [
"success"
],
"title": "FindSharedFolderEmailOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"displayName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Displayname"
},
"mail": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mail"
},
"userPrincipalName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Userprincipalname"
}
},
"required": [
"success"
],
"title": "GetCurrentUserOutput",
"type": "object"
}
```
### Parameters
The Microsoft Graph message ID.
If true, expands attachments on the returned message. (Default: `false`)
The User ID of a shared mailbox.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "GetMessageOutput",
"type": "object"
}
```
### Parameters
If provided, only contacts with the given email address will be retrieved.
Maximum number of contacts to return. (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"contacts": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Contacts",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListContactsOutput",
"type": "object"
}
```
### Parameters
Maximum number of folders to return. (Default: `100`)
If true, recursively include subfolders. (Default: `false`)
If true, include hidden folders. (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"folders": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Folders",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListFoldersOutput",
"type": "object"
}
```
### Parameters
Maximum number of messages to return. (Default: `100`)
The User ID of a shared mailbox.
### Response
```json
{
"$defs": {
"ImportantMailItem": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"sender": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sender"
},
"receivedDateTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Receiveddatetime"
}
},
"title": "ImportantMailItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"data": {
"items": {
"$ref": "#/$defs/ImportantMailItem"
},
"title": "Data",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListImportantMailOutput",
"type": "object"
}
```
### Parameters
The User ID of a shared mailbox.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"labels": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Labels",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListLabelsOutput",
"type": "object"
}
```
### Parameters
The identifier of the message to move.
The identifier of the destination folder.
The User ID of a shared mailbox.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"parentFolderId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Parentfolderid"
}
},
"required": [
"success"
],
"title": "MoveEmailToFolderOutput",
"type": "object"
}
```
### Parameters
The identifier of the message to update.
The name of the label/category to remove.
The User ID of a shared mailbox.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"categories": {
"items": {
"type": "string"
},
"title": "Categories",
"type": "array"
}
},
"required": [
"success"
],
"title": "RemoveLabelFromEmailOutput",
"type": "object"
}
```
### Parameters
The identifier of the message to reply to.
Content of the reply in text format.
Optional override for TO recipients (list of strings).
CC recipient email addresses (list of strings).
BCC recipient email addresses (list of strings).
Optional subject override.
Array of file URLs to attach (list of strings).
Additional Message resource fields merged into the reply body.
The User ID of a shared mailbox.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"sent": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Sent"
}
},
"required": [
"success"
],
"title": "ReplyToEmailOutput",
"type": "object"
}
```
### Parameters
TO recipient email addresses (list of strings).
CC recipient email addresses (list of strings).
BCC recipient email addresses (list of strings).
Subject of the email.
Content type of the body. Valid values: text, html. (Default: `text`)
Body content of the email.
Array of file URLs to fetch and attach (list of strings).
Additional Message resource fields merged into the request.
The User ID of a shared mailbox.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"sent": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Sent"
}
},
"required": [
"success"
],
"title": "SendEmailOutput",
"type": "object"
}
```
### Parameters
The ID of the contact to update.
Given name of the contact.
Surname of the contact.
Replacement email addresses for the contact (list of strings).
Replacement phone numbers (list of strings).
Additional contact fields merged into the request body.
### Response
```json
{
"$defs": {
"ContactSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"displayName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Displayname"
},
"givenName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Givenname"
},
"surname": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Surname"
},
"emailAddresses": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Emailaddresses",
"type": "array"
},
"businessPhones": {
"items": {
"type": "string"
},
"title": "Businessphones",
"type": "array"
}
},
"title": "ContactSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"contact": {
"anyOf": [
{
"$ref": "#/$defs/ContactSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UpdateContactOutput",
"type": "object"
}
```
## Limits & Quotas
- Microsoft Graph throttles per-app and per-mailbox. Mail endpoints allow approximately 10,000 requests per 10 minutes per app per mailbox; consult Microsoft's throttling guidance for exact tiers.
- Search uses Microsoft Graph KQL semantics; combining `search` with `filter` or `order_by` is rejected by Microsoft Graph and short-circuited locally with a `success=False` error.
- Attachments are accepted as URLs only; the integration fetches each URL and base64-encodes the bytes for Microsoft Graph's `fileAttachment` payload. `download_attachment` returns base64-encoded bytes rather than writing files to disk.
- The `approve_workflow` action does not internally suspend a workflow; the caller must supply both `resume_url` and `cancel_url`. The action only sends the approval email.
- Error model: non-2xx responses are caught and returned as `success=False` + `error`; the calling agent can retry or surface the error.
## Related integrations
## Links
- [Microsoft Outlook](https://outlook.live.com)
---
# Microsoft Power BI Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/microsoft-power-bi
Business intelligence and analytics platform for interactive visualizations, reports, and dashboards
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/microsoft_power_bi/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Microsoft Power BI** to any ModuleX agent or workflow. Business intelligence and analytics platform integration against the Power BI REST API (`api.powerbi.com/v1.0/myorg`).
**Categories**: Analytics & Data · Business Intelligence · Analytics · Productivity · **Auth**: OAuth2 (Microsoft Entra ID) · **Actions**: 10
## Authentication
### OAuth2 (Microsoft Entra ID)
Connect using Microsoft OAuth2 (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Microsoft Entra ID App Registration Client ID | Yes | `-` |
| Client Secret | Microsoft Entra ID App Registration Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/authorize`
- **Token URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/token`
- **Scopes**: `https://analysis.windows.net/powerbi/api/.default`, `offline_access`
## Available Actions
### Parameters
ID of the Push Dataset (use list_datasets to find IDs)
Exact case-sensitive name of the table within the dataset
JSON array of row objects matching the table column schema
ID of the workspace (omit for My workspace)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"rows_added": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Rows Added"
}
},
"required": [
"success"
],
"title": "AddRowsToPushDatasetOutput",
"type": "object"
}
```
### Parameters
ID of the dataset to query (use list_datasets to find IDs)
DAX expression starting with EVALUATE
ID of the workspace (omit for My workspace)
Whether to include null values in the response (Default: `true`)
UPN of an effective identity for Row-Level Security
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"results": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Results",
"type": "array"
}
},
"required": [
"success"
],
"title": "ExecuteDaxQueryOutput",
"type": "object"
}
```
### Parameters
ID of the report to export (use list_reports to find IDs)
Output format: PDF, PPTX, PNG, CSV, XLSX, DOCX, XML, MHTML (Default: `PDF`)
ID of the workspace (omit for My workspace)
Seconds between export status polls (Default: `5`)
Maximum seconds to wait for export completion (Default: `300`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"export_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Export Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"report_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Report Id"
},
"format": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Format"
},
"resource_file_extension": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Resource File Extension"
},
"resource_location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Resource Location"
},
"file_size_bytes": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "File Size Bytes"
},
"file_base64": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "File Base64"
},
"percent_complete": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Percent Complete"
}
},
"required": [
"success"
],
"title": "ExportReportOutput",
"type": "object"
}
```
### Parameters
ID of the dataset (use list_datasets to find IDs)
ID of the workspace (omit for My workspace)
Number of most recent refresh entries to return (max 200)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"refreshes": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Refreshes",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetRefreshHistoryOutput",
"type": "object"
}
```
### Parameters
Power BI report ID (GUID)
Workspace group ID (omit for My workspace)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"web_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Web Url"
},
"embed_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Embed Url"
},
"dataset_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Dataset Id"
},
"report_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Report Type"
}
},
"required": [
"success"
],
"title": "GetReportsByIdOutput",
"type": "object"
}
```
### Parameters
ID of the workspace (omit for My workspace)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"dashboards": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Dashboards",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListDashboardsOutput",
"type": "object"
}
```
### Parameters
ID of the workspace (omit for My workspace)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"datasets": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Datasets",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListDatasetsOutput",
"type": "object"
}
```
### Parameters
ID of the workspace (omit for My workspace)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"reports": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Reports",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListReportsOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"workspaces": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Workspaces",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListWorkspacesOutput",
"type": "object"
}
```
### Parameters
ID of the dataset to refresh (use list_datasets to find IDs)
ID of the workspace (omit for My workspace)
Email notification behavior: NoNotification, MailOnCompletion, MailOnFailure (Default: `NoNotification`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"status_code": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Status Code"
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Request Id"
},
"dataset_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Dataset Id"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Location"
}
},
"required": [
"success"
],
"title": "RefreshDatasetOutput",
"type": "object"
}
```
## Limits & Quotas
- Power BI REST API is rate-limited per user/app; exact limits depend on capacity (shared vs Premium).
- Dataset refreshes: Pro allows up to 8/day; Premium allows up to 48/day.
- DAX query execution timeout: 5 minutes server-side.
- Export API: Premium-only; exports may take minutes for large reports.
- Error model: non-2xx responses are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Microsoft Power BI](https://powerbi.microsoft.com)
---
# Microsoft SQL Server Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/microsoft-sql-server
Execute queries and manage data in Microsoft SQL Server databases
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/microsoft_sql_server/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Microsoft SQL Server** to any ModuleX agent or workflow. Execute queries and manage data in Microsoft SQL Server databases via direct TCP connections using `pymssql`.
**Categories**: Databases · Data Infrastructure · **Auth**: SQL Server Connection · **Actions**: 4
## Authentication
### SQL Server Connection
Connect using SQL Server host, port, database, username, and password
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Host | SQL Server hostname or IP address | Yes | `myserver.database.windows.net` |
| Port | SQL Server port number | Yes | `1433` |
| Username | SQL Server login username | Yes | `-` |
| Password | SQL Server login password | Yes | `-` |
| Database | Name of the database to connect to | Yes | `-` |
| Encrypt | Whether to encrypt the connection (true/false). Use true for Azure SQL. | No | `true` |
| Trust Server Certificate | Whether to trust self-signed certificates (true/false). Use true for local dev. | No | `false` |
## Available Actions
### Parameters
The SQL query to execute
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"recordset": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Recordset",
"type": "array"
},
"rows_affected": {
"items": {
"type": "integer"
},
"title": "Rows Affected",
"type": "array"
}
},
"required": [
"success"
],
"title": "ExecuteRawQueryOutput",
"type": "object"
}
```
### Parameters
The SQL query to execute, using @name placeholders for parameters
Key-value mapping of parameter names to values for the query placeholders
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"recordset": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Recordset",
"type": "array"
},
"rows_affected": {
"items": {
"type": "integer"
},
"title": "Rows Affected",
"type": "array"
}
},
"required": [
"success"
],
"title": "ExecuteQueryOutput",
"type": "object"
}
```
### Parameters
Name of the table to insert into
JSON object mapping column names to values for the new row
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"rows_affected": {
"items": {
"type": "integer"
},
"title": "Rows Affected",
"type": "array"
}
},
"required": [
"success"
],
"title": "InsertRowOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"tables": {
"items": {
"type": "string"
},
"title": "Tables",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListTableOptionsOutput",
"type": "object"
}
```
## Limits & Quotas
- No API rate limits apply; performance depends on the SQL Server instance capacity and network latency.
- Connection timeout defaults to pymssql's default (dependent on server responsiveness).
- Query execution is wrapped in `asyncio.to_thread` so it does not block the event loop.
- Error model: connection failures, query syntax errors, and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Microsoft SQL Server](https://www.microsoft.com/en-us/sql-server)
---
# Microsoft Teams Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/microsoft-teams
Create channels, send channel and chat messages, list teams/channels/chats/messages/shifts, search messages, and retrieve the current user via Microsoft Graph.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/microsoft_teams/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Microsoft Teams** to any ModuleX agent or workflow. Create channels, send channel and chat messages, list teams / channels / chats / messages / shifts, search messages, and retrieve the current user via the Microsoft Graph REST API (`graph.microsoft.com/v1.0`).
**Categories**: Communication · Productivity & Collaboration · **Auth**: OAuth2 · **Actions**: 12
## Authentication
### OAuth2 Authentication
Connect with your Microsoft work or school account using OAuth 2.0. Personal accounts are not supported by Microsoft Teams APIs.
Go to https://entra.microsoft.com (Microsoft Entra admin center) and open 'App registrations'
Create a new registration (single-tenant or multi-tenant, as required by your deployment)
Under Authentication, add the redirect URI: https://api.modulex.dev/credentials/oauth2/callback (type: Web)
Under API permissions, add Microsoft Graph delegated permissions: User.Read, Team.ReadBasic.All, Channel.ReadBasic.All, ChannelMessage.Read.All, ChannelMessage.Send, Chat.ReadWrite, ChatMessage.Send, Schedule.Read.All, Mail.Read, and offline_access
Grant admin consent for the tenant if your organization requires it
Under Certificates & secrets, create a Client Secret and copy its Value
Copy the Application (client) ID and the Client Secret Value into ModuleX
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Microsoft Entra Application (client) ID for the registered app. | Yes | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
| Client Secret | Microsoft Entra Client Secret Value for the registered app. | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/authorize`
- **Token URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/token`
- **Scopes**: `offline_access`, `User.Read`, `Team.ReadBasic.All`, `Channel.ReadBasic.All`, `ChannelMessage.Read.All`, `ChannelMessage.Send`, `Chat.ReadWrite`, `ChatMessage.Send`, `Schedule.Read.All`, `Mail.Read`
## Available Actions
### Parameters
ID of the Microsoft Team. Obtain it via `list_teams`.
Display name of the channel.
Description of the channel.
### Response
```json
{
"$defs": {
"ChannelResource": {
"additionalProperties": false,
"description": "Microsoft Graph Channel resource.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"displayName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Displayname"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"membershipType": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Membershiptype"
},
"webUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Weburl"
}
},
"title": "ChannelResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"channel": {
"anyOf": [
{
"$ref": "#/$defs/ChannelResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateChannelOutput",
"type": "object"
}
```
### Parameters
ID of the chat. Obtain it via `list_chats`.
ID of the message to retrieve. Obtain it via `list_messages_in_chat`.
### Response
```json
{
"$defs": {
"ChatMessageResource": {
"additionalProperties": false,
"description": "Microsoft Graph chatMessage resource (permissive — upstream returns many optional fields).",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"createdDateTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Createddatetime"
},
"from": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "From"
},
"body": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Body"
},
"importance": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Importance"
},
"webUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Weburl"
}
},
"title": "ChatMessageResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"$ref": "#/$defs/ChatMessageResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetChatMessageOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"CurrentUser": {
"additionalProperties": false,
"description": "Subset of Microsoft Graph user resource returned by get_current_user.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"displayName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Displayname"
},
"mail": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mail"
},
"userPrincipalName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Userprincipalname"
}
},
"title": "CurrentUser",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"user": {
"anyOf": [
{
"$ref": "#/$defs/CurrentUser"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetCurrentUserOutput",
"type": "object"
}
```
### Parameters
ID of the Microsoft Team.
ID of the channel within the team.
The maximum number of messages to return. Omit to fetch all available pages.
### Response
```json
{
"$defs": {
"ChatMessageResource": {
"additionalProperties": false,
"description": "Microsoft Graph chatMessage resource (permissive — upstream returns many optional fields).",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"createdDateTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Createddatetime"
},
"from": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "From"
},
"body": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Body"
},
"importance": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Importance"
},
"webUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Weburl"
}
},
"title": "ChatMessageResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"messages": {
"items": {
"$ref": "#/$defs/ChatMessageResource"
},
"title": "Messages",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListChannelMessagesOutput",
"type": "object"
}
```
### Parameters
ID of the Microsoft Team.
### Response
```json
{
"$defs": {
"ChannelResource": {
"additionalProperties": false,
"description": "Microsoft Graph Channel resource.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"displayName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Displayname"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"membershipType": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Membershiptype"
},
"webUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Weburl"
}
},
"title": "ChannelResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"channels": {
"items": {
"$ref": "#/$defs/ChannelResource"
},
"title": "Channels",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListChannelsOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"ChatResource": {
"additionalProperties": false,
"description": "Microsoft Graph Chat resource (with members expanded).",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"topic": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Topic"
},
"chatType": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Chattype"
},
"createdDateTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Createddatetime"
},
"lastUpdatedDateTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lastupdateddatetime"
},
"webUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Weburl"
},
"members": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Members",
"type": "array"
}
},
"title": "ChatResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"chats": {
"items": {
"$ref": "#/$defs/ChatResource"
},
"title": "Chats",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListChatsOutput",
"type": "object"
}
```
### Parameters
ID of the chat.
The maximum number of results to return. Omit to fetch all available pages.
### Response
```json
{
"$defs": {
"ChatMessageResource": {
"additionalProperties": false,
"description": "Microsoft Graph chatMessage resource (permissive — upstream returns many optional fields).",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"createdDateTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Createddatetime"
},
"from": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "From"
},
"body": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Body"
},
"importance": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Importance"
},
"webUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Weburl"
}
},
"title": "ChatMessageResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"messages": {
"items": {
"$ref": "#/$defs/ChatMessageResource"
},
"title": "Messages",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListMessagesInChatOutput",
"type": "object"
}
```
### Parameters
ID of the Microsoft Team whose schedule is being queried.
### Response
```json
{
"$defs": {
"ShiftResource": {
"additionalProperties": false,
"description": "Microsoft Graph Shift resource.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"userId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Userid"
},
"schedulingGroupId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Schedulinggroupid"
},
"createdDateTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Createddatetime"
},
"lastModifiedDateTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lastmodifieddatetime"
},
"sharedShift": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Sharedshift"
},
"draftShift": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Draftshift"
}
},
"title": "ShiftResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"shifts": {
"items": {
"$ref": "#/$defs/ShiftResource"
},
"title": "Shifts",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListShiftsOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"TeamResource": {
"additionalProperties": false,
"description": "Microsoft Graph Team resource.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"displayName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Displayname"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"visibility": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Visibility"
},
"webUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Weburl"
}
},
"title": "TeamResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"teams": {
"items": {
"$ref": "#/$defs/TeamResource"
},
"title": "Teams",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListTeamsOutput",
"type": "object"
}
```
### Parameters
The type of entity to search for. Valid values: `message` for email, `chatMessage` for Teams chat messages.
The query string to search for.
The index of the first result to return. (Default: `0`)
The number of results to return (max 25). (Default: `25`)
### Response
```json
{
"$defs": {
"SearchResponse": {
"additionalProperties": false,
"description": "Microsoft Graph search response wrapper.",
"properties": {
"value": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Value",
"type": "array"
}
},
"title": "SearchResponse",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"anyOf": [
{
"$ref": "#/$defs/SearchResponse"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "SearchMessagesOutput",
"type": "object"
}
```
### Parameters
ID of the Microsoft Team.
ID of the channel within the team.
Message to be sent.
Whether the message body is plain text or HTML. Valid values: `text`, `html`. (Default: `text`)
An array of JSON strings, each representing an inline hosted image. Each item must be a JSON object with `@microsoft.graph.temporaryId` (string), `contentBytes` (base64-encoded image data), and `contentType` (MIME type, e.g. `image/png`). Reference each image in HTML message bodies using `
`.
### Response
```json
{
"$defs": {
"ChatMessageResource": {
"additionalProperties": false,
"description": "Microsoft Graph chatMessage resource (permissive — upstream returns many optional fields).",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"createdDateTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Createddatetime"
},
"from": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "From"
},
"body": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Body"
},
"importance": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Importance"
},
"webUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Weburl"
}
},
"title": "ChatMessageResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"$ref": "#/$defs/ChatMessageResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "SendChannelMessageOutput",
"type": "object"
}
```
### Parameters
ID of the chat to post the message to.
Message to be sent.
Whether the message body is plain text or HTML. Valid values: `text`, `html`. (Default: `text`)
### Response
```json
{
"$defs": {
"ChatMessageResource": {
"additionalProperties": false,
"description": "Microsoft Graph chatMessage resource (permissive — upstream returns many optional fields).",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"createdDateTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Createddatetime"
},
"from": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "From"
},
"body": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Body"
},
"importance": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Importance"
},
"webUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Weburl"
}
},
"title": "ChatMessageResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message": {
"anyOf": [
{
"$ref": "#/$defs/ChatMessageResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "SendChatMessageOutput",
"type": "object"
}
```
## Limits & Quotas
- Microsoft Graph applies per-app, per-tenant, and per-resource throttling. Teams messaging endpoints have specific RU-based limits documented at https://learn.microsoft.com/en-us/graph/throttling. Retry on HTTP 429 honoring the `Retry-After` header.
- `search_messages` returns at most 25 results per call (upper bound enforced by the Microsoft Graph search API for this entity-type set). Use the `from_` parameter to page beyond the first window.
- Dynamic team / channel / chat / message pickers are not available — pass IDs directly; use the corresponding `list_*` action to enumerate IDs.
- Webhook / change-notification subscriptions are not part of this integration; polling via the `list_*` actions is the supported pattern.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` plus an `error` string rather than raising. Plan for retries on the agent side based on the error text.
## Related integrations
## Links
- [Microsoft Teams](https://www.microsoft.com/microsoft-teams)
---
# Mintlify Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/mintlify
Documentation platform with AI-powered assistant, semantic search, and project update triggers.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/mintlify/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Mintlify** to any ModuleX agent or workflow. Documentation platform with AI-powered assistant chat, semantic search, and project update triggers against the Mintlify REST APIs (`api-dsc.mintlify.com/v1` and `api.mintlify.com/v1`).
**Categories**: Developer Tools & Infrastructure · Documentation · **Auth**: Mintlify API Keys · **Actions**: 3
## Authentication
### Mintlify API Keys
Authenticate using Mintlify assistant API key, admin API key, and project ID. Different actions use different credentials.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Assistant API Key | Your Mintlify Assistant API key for chat and search endpoints. | Yes | `-` |
| Admin API Key | Your Mintlify Admin API key for triggering project updates. | Yes | `-` |
| Project ID | Your Mintlify project ID used for update triggers. | Yes | `-` |
## Available Actions
### Parameters
The domain identifier from your domain.mintlify.app URL. Can be found in the top left of your dashboard.
Browser fingerprint or arbitrary string identifier for message tracking.
The content of the message to send to the assistant.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"message_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message Id"
},
"response": {
"anyOf": [
{},
{
"type": "null"
}
],
"default": null,
"title": "Response"
}
},
"required": [
"success"
],
"title": "ChatWithAssistantOutput",
"type": "object"
}
```
### Parameters
The domain identifier from your domain.mintlify.app URL. Can be found in the top left of your dashboard.
The search query to execute against your documentation content.
Number of search results to return. Defaults to 10 if not specified.
Filter results by documentation version.
Filter results by content language.
### Response
```json
{
"$defs": {
"SearchResultItem": {
"additionalProperties": false,
"description": "A single search result from the documentation.",
"properties": {
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"content": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content"
},
"score": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Score"
}
},
"title": "SearchResultItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"results": {
"items": {
"$ref": "#/$defs/SearchResultItem"
},
"title": "Results",
"type": "array"
},
"total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total"
}
},
"required": [
"success"
],
"title": "SearchDocumentationOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "TriggerUpdateOutput",
"type": "object"
}
```
## Limits & Quotas
- No publicly documented rate limits for the Mintlify API.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Mintlify](https://www.mintlify.com)
---
# Mixpanel Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/mixpanel
Product analytics platform for tracking user events and behaviors
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/mixpanel/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Mixpanel** to any ModuleX agent or workflow. Product analytics platform for tracking user events and behaviors via the Mixpanel Track API (`api.mixpanel.com`).
**Categories**: Analytics & Data · Analytics · Product Analytics · **Auth**: Project Token · **Actions**: 1
## Authentication
### Project Token
Authenticate using your Mixpanel Project Token for event ingestion
Sign in at https://mixpanel.com
Go to Settings > Project Settings
Copy your Project Token
Paste the token below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Project Token | Your Mixpanel Project Token from Settings > Project Settings | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
| Ingestion Base URL | Mixpanel ingestion base URL (optional — leave empty for https://api.mixpanel.com US default). Set to https://api-eu.mixpanel.com for EU data residency projects. | No | `https://api.mixpanel.com` |
## Available Actions
### Parameters
The name of the event (e.g. 'Button Click', 'Sign Up', 'Item Purchased')
The unique identifier for the user performing the event
A set of properties to include with the event describing the user or event details
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"distinct_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Distinct Id"
},
"properties": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Properties"
}
},
"required": [
"success"
],
"title": "EmitEventToOutput",
"type": "object"
}
```
## Limits & Quotas
- No documented per-token rate limits for the Track API ingestion endpoint.
- Mixpanel recommends batching events (up to 2000 per request) for high-volume use cases; this integration sends one event per call.
- Error model: non-2xx responses and Mixpanel rejections (response body `0`) are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Mixpanel](https://mixpanel.com)
---
# Monday.com Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/monday
Monday.com work management platform for boards, items, columns, and updates via the GraphQL API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/monday/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Monday.com** to any ModuleX agent or workflow. Work management platform for creating and managing boards, items, columns, groups, and updates via the Monday.com GraphQL API (`api.monday.com/v2`).
**Categories**: Project & Task Management · Productivity & Collaboration · Project Management · **Auth**: OAuth2, API Key · **Actions**: 13
## Authentication
### OAuth2 Authentication
Connect using Monday.com OAuth (recommended for most use cases)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Monday.com OAuth App Client ID | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
| Client Secret | Monday.com OAuth App Client Secret | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://auth.monday.com/oauth2/authorize`
- **Token URL**: `https://auth.monday.com/oauth2/token`
- **Scopes**: `me:read`, `boards:read`, `boards:write`, `workspaces:read`
### API Key Authentication
Authenticate using your Monday.com API token
Sign in to your Monday.com account
Click your avatar (bottom left) and select 'Developers'
Go to 'My Access Tokens' section
Copy your personal API token or generate a new one
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Monday.com API Token | Your personal API token from Monday.com developer settings | Yes | `eyJhbGciOiJIUzI1NiJ9...` |
## Available Actions
### Parameters
The new board's name
The new board's kind: public, private, or share
Workspace ID to create the board in. If not specified, the Main Workspace is used
Folder ID to create the board in
Template board ID to use for the new board
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
}
},
"required": [
"success"
],
"title": "CreateBoardOutput",
"type": "object"
}
```
### Parameters
The ID of the board to create the column in
The title of the new column
The type of column: auto_number, checkbox, country, color_picker, creation_log, date, dependency, dropdown, email, file, hour, item_id, last_updated, link, location, long_text, numbers, people, phone, progress, rating, status, team, tags, text, timeline, time_tracking, vote, week, world_clock
Custom labels JSON for status/dropdown columns, e.g. {"1": "Technology", "2": "Marketing"}
Description of the new column
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
}
},
"required": [
"success"
],
"title": "CreateColumnOutput",
"type": "object"
}
```
### Parameters
The ID of the board to create the group in
The name of the new group
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
}
},
"required": [
"success"
],
"title": "CreateGroupOutput",
"type": "object"
}
```
### Parameters
The ID of the board to create the item in
The new item's name
Group ID to create the item in
Create Status/Dropdown labels if missing (requires permission to change board structure)
JSON string of column values for the new item. See Monday.com Column Type Reference for format details
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
}
},
"required": [
"success"
],
"title": "CreateItemOutput",
"type": "object"
}
```
### Parameters
The ID of the board containing the parent item
The ID of the parent item to create the subitem under
The new subitem's name
JSON string of column values for the new subitem
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
}
},
"required": [
"success"
],
"title": "CreateSubitemOutput",
"type": "object"
}
```
### Parameters
The ID of the board containing the item
The ID of the item to add the update to
The update text content
The ID of a parent update to reply to
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
}
},
"required": [
"success"
],
"title": "CreateUpdateOutput",
"type": "object"
}
```
### Parameters
The ID of the board to retrieve items from
JSON object with filter/sort parameters in ItemsQuery format
Maximum number of pages to fetch (default 50) (Default: `50`)
### Response
```json
{
"$defs": {
"ColumnValue": {
"additionalProperties": false,
"description": "A column value returned for an item.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"value": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
},
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
}
},
"title": "ColumnValue",
"type": "object"
},
"ItemSummary": {
"additionalProperties": false,
"description": "An item returned from a Monday.com board.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"column_values": {
"items": {
"$ref": "#/$defs/ColumnValue"
},
"title": "Column Values",
"type": "array"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"creator_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Creator Id"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"relative_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Relative Link"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
}
},
"title": "ItemSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"$ref": "#/$defs/ItemSummary"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetBoardItemsPageOutput",
"type": "object"
}
```
### Parameters
The ID of the board
The ID of the item to retrieve column values from
List of column IDs to retrieve. If empty, returns all columns. Element type: string
### Response
```json
{
"$defs": {
"ColumnValue": {
"additionalProperties": false,
"description": "A column value returned for an item.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"value": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
},
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
}
},
"title": "ColumnValue",
"type": "object"
},
"ItemSummary": {
"additionalProperties": false,
"description": "An item returned from a Monday.com board.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"column_values": {
"items": {
"$ref": "#/$defs/ColumnValue"
},
"title": "Column Values",
"type": "array"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"creator_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Creator Id"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"relative_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Relative Link"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
}
},
"title": "ItemSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"$ref": "#/$defs/ItemSummary"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetColumnValuesOutput",
"type": "object"
}
```
### Parameters
The ID of the board to search in
The ID of the column to search
The value to search for in the specified column
Maximum number of pages to fetch (default 50) (Default: `50`)
### Response
```json
{
"$defs": {
"ColumnValue": {
"additionalProperties": false,
"description": "A column value returned for an item.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"value": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
},
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
}
},
"title": "ColumnValue",
"type": "object"
},
"ItemSummary": {
"additionalProperties": false,
"description": "An item returned from a Monday.com board.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"column_values": {
"items": {
"$ref": "#/$defs/ColumnValue"
},
"title": "Column Values",
"type": "array"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"creator_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Creator Id"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"relative_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Relative Link"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
}
},
"title": "ItemSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"$ref": "#/$defs/ItemSummary"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetItemsByColumnValueOutput",
"type": "object"
}
```
### Parameters
Filter to specific board IDs. Element type: string
Filter to boards in specific workspace IDs. Element type: integer
Filter by board kind: public, private, or share
Filter by state: active, archived, deleted, or all (Default: `all`)
Sort by: created_at or used_at (Default: `created_at`)
Maximum number of boards to return per page (Default: `25`)
Page number to return (Default: `1`)
### Response
```json
{
"$defs": {
"MondayBoard": {
"additionalProperties": false,
"description": "A board object from Monday.com.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"board_kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Board Kind"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"workspace_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Workspace Id"
}
},
"title": "MondayBoard",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"boards": {
"items": {
"$ref": "#/$defs/MondayBoard"
},
"title": "Boards",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListBoardsOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"WorkspaceOption": {
"additionalProperties": false,
"description": "A workspace option with label and value.",
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Label"
},
"value": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
}
},
"title": "WorkspaceOption",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"workspaces": {
"items": {
"$ref": "#/$defs/WorkspaceOption"
},
"title": "Workspaces",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListWorkspacesOutput",
"type": "object"
}
```
### Parameters
The ID of the board containing the item
The ID of the item to update
JSON string of column values to update. Keys are column IDs, values are new values per Column Types Reference
### Response
```json
{
"$defs": {
"ColumnValue": {
"additionalProperties": false,
"description": "A column value returned for an item.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"value": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
},
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
}
},
"title": "ColumnValue",
"type": "object"
},
"ItemSummary": {
"additionalProperties": false,
"description": "An item returned from a Monday.com board.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"column_values": {
"items": {
"$ref": "#/$defs/ColumnValue"
},
"title": "Column Values",
"type": "array"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"creator_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Creator Id"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"relative_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Relative Link"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
}
},
"title": "ItemSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"$ref": "#/$defs/ItemSummary"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "UpdateColumnValuesOutput",
"type": "object"
}
```
### Parameters
The ID of the board containing the item
The ID of the item to rename
The new item name
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
}
},
"required": [
"success"
],
"title": "UpdateItemNameOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limits**: Monday.com uses a complexity-based rate limit system. Each query has a complexity cost; the default limit is 10,000,000 complexity points per minute.
- **Pagination**: Board items are paginated with a default page size of 500 items per request. The integration handles cursor-based pagination internally for `get_board_items_page` and `get_items_by_column_value`.
- **Error model**: GraphQL errors and non-2xx responses are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Monday.com](https://monday.com)
---
# Motion Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/motion
AI-powered task and project management platform for automatic scheduling
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/motion/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Motion** to any ModuleX agent or workflow. AI-powered task and project management platform with automatic scheduling, accessed via the Motion REST API (`api.usemotion.com/v1`).
**Categories**: Project & Task Management · Productivity & Collaboration · Project Management · **Auth**: API Key · **Actions**: 6
## Authentication
### API Key Authentication
Authenticate using your Motion API key
Go to https://app.usemotion.com and sign in
Navigate to Settings > API
Generate a new API key or copy your existing one
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Motion API Key | Your Motion API key from the Settings > API page | Yes | `xxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
The ID of the workspace
Name / title of the task
The ID of the project to assign the task to
ISO 8601 due date. Required for scheduled tasks. Example: 2023-06-28T10:11:14.320-06:00
Duration: NONE, REMINDER, or an integer greater than 0
Task description in GitHub Flavored Markdown
Priority level: ASAP, HIGH, MEDIUM, LOW (Default: `MEDIUM`)
The user ID to assign the task to
List of label names to add to the task
The name of the task status
ISO 8601 date for auto-scheduled tasks. Example: 2023-06-28
Deadline type for auto-scheduled tasks: HARD, SOFT, NONE
Schedule the task must adhere to. Must be 'Work Hours' if scheduling for another user (Default: `Work Hours`)
### Response
```json
{
"$defs": {
"TaskObject": {
"additionalProperties": false,
"description": "A Motion task object returned by task-related actions.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"status": {
"anyOf": [
{
"$ref": "#/$defs/TaskStatus"
},
{
"type": "null"
}
],
"default": null
},
"workspace_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Workspace Id"
},
"project_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Project Id"
},
"priority": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Priority"
},
"assignee_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Assignee Id"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
},
"due_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Due Date"
},
"duration": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Duration"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
}
},
"title": "TaskObject",
"type": "object"
},
"TaskStatus": {
"additionalProperties": false,
"description": "Status information for a task.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"is_default_status": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Default Status"
},
"is_resolved_status": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Resolved Status"
}
},
"title": "TaskStatus",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"task": {
"anyOf": [
{
"$ref": "#/$defs/TaskObject"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateTaskOutput",
"type": "object"
}
```
### Parameters
The ID of the task to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "DeleteTaskOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"ScheduleItem": {
"additionalProperties": false,
"description": "A schedule object returned by the get_schedules action.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"timezone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timezone"
},
"is_default": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Default"
}
},
"title": "ScheduleItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"schedules": {
"items": {
"$ref": "#/$defs/ScheduleItem"
},
"title": "Schedules",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetSchedulesOutput",
"type": "object"
}
```
### Parameters
The ID of the task to retrieve
### Response
```json
{
"$defs": {
"TaskObject": {
"additionalProperties": false,
"description": "A Motion task object returned by task-related actions.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"status": {
"anyOf": [
{
"$ref": "#/$defs/TaskStatus"
},
{
"type": "null"
}
],
"default": null
},
"workspace_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Workspace Id"
},
"project_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Project Id"
},
"priority": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Priority"
},
"assignee_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Assignee Id"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
},
"due_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Due Date"
},
"duration": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Duration"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
}
},
"title": "TaskObject",
"type": "object"
},
"TaskStatus": {
"additionalProperties": false,
"description": "Status information for a task.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"is_default_status": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Default Status"
},
"is_resolved_status": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Resolved Status"
}
},
"title": "TaskStatus",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"task": {
"anyOf": [
{
"$ref": "#/$defs/TaskObject"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetTaskOutput",
"type": "object"
}
```
### Parameters
The ID of the task to move
The ID of the target workspace
The user ID to assign the task to in the target workspace
### Response
```json
{
"$defs": {
"TaskObject": {
"additionalProperties": false,
"description": "A Motion task object returned by task-related actions.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"status": {
"anyOf": [
{
"$ref": "#/$defs/TaskStatus"
},
{
"type": "null"
}
],
"default": null
},
"workspace_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Workspace Id"
},
"project_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Project Id"
},
"priority": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Priority"
},
"assignee_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Assignee Id"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
},
"due_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Due Date"
},
"duration": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Duration"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
}
},
"title": "TaskObject",
"type": "object"
},
"TaskStatus": {
"additionalProperties": false,
"description": "Status information for a task.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"is_default_status": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Default Status"
},
"is_resolved_status": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Resolved Status"
}
},
"title": "TaskStatus",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"task": {
"anyOf": [
{
"$ref": "#/$defs/TaskObject"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "MoveWorkspaceOutput",
"type": "object"
}
```
### Parameters
The ID of the task to update
New name / title for the task
ISO 8601 due date. Example: 2023-06-28T10:11:14.320-06:00
Duration: NONE, REMINDER, or an integer greater than 0
The ID of the project to assign the task to
Task description in GitHub Flavored Markdown
Priority level: ASAP, HIGH, MEDIUM, LOW (Default: `MEDIUM`)
The user ID to assign the task to
List of label names to add to the task
The name of the task status
ISO 8601 date for auto-scheduled tasks. Example: 2023-06-28
Deadline type for auto-scheduled tasks: HARD, SOFT, NONE
Schedule the task must adhere to. Must be 'Work Hours' if scheduling for another user (Default: `Work Hours`)
### Response
```json
{
"$defs": {
"TaskObject": {
"additionalProperties": false,
"description": "A Motion task object returned by task-related actions.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"status": {
"anyOf": [
{
"$ref": "#/$defs/TaskStatus"
},
{
"type": "null"
}
],
"default": null
},
"workspace_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Workspace Id"
},
"project_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Project Id"
},
"priority": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Priority"
},
"assignee_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Assignee Id"
},
"labels": {
"items": {
"type": "string"
},
"title": "Labels",
"type": "array"
},
"due_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Due Date"
},
"duration": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Duration"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
}
},
"title": "TaskObject",
"type": "object"
},
"TaskStatus": {
"additionalProperties": false,
"description": "Status information for a task.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"is_default_status": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Default Status"
},
"is_resolved_status": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Resolved Status"
}
},
"title": "TaskStatus",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"task": {
"anyOf": [
{
"$ref": "#/$defs/TaskObject"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UpdateTaskOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limit**: 12 requests per minute per API key (Motion API documentation).
- **Pricing**: API access requires a Motion Individual or Team plan.
- **Error model**: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Motion](https://www.usemotion.com)
---
# MySQL Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/mysql
MySQL database integration for executing SQL queries, managing tables, and performing CRUD operations. Uses the aiomysql driver.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/mysql/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **MySQL** to any ModuleX agent or workflow. MySQL database integration via the `aiomysql` driver. Provides raw SQL execution + CRUD + stored procedures + introspection.
**Categories**: Databases · Database · Data Management · Storage · **Auth**: MySQL Database Credentials · **Actions**: 9
## Authentication
### MySQL Database Credentials
Authenticate using MySQL connection credentials (host/port/user/password/database).
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Host | MySQL server hostname or IP | Yes | `localhost or mysql.example.com` |
| Port | MySQL server port (defaults to 3306 if omitted) | No | `3306` |
| Username | MySQL username for authentication | Yes | `-` |
| Password | MySQL password for authentication | Yes | `-` |
| Database | The database name to connect to | Yes | `-` |
| SSL Mode | SSL mode: 'disabled', 'verify' (default), or 'skip_verification' | No | `verify | skip_verification | disabled` |
## Available Actions
### Parameters
The SQL to execute
Values for '%s' placeholders
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"row_count": {
"default": 0,
"title": "Row Count",
"type": "integer"
},
"data": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Data",
"type": "array"
}
},
"required": [
"success"
],
"title": "ExecuteRawQueryOutput",
"type": "object"
}
```
### Parameters
The table name
Column-value pairs to insert
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"table": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Table"
},
"affected_rows": {
"default": 0,
"title": "Affected Rows",
"type": "integer"
},
"last_insert_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Insert Id"
},
"columns": {
"items": {
"type": "string"
},
"title": "Columns",
"type": "array"
}
},
"required": [
"success"
],
"title": "CreateRowOutput",
"type": "object"
}
```
### Parameters
The table name
WHERE condition with '?' placeholders
Values matching the '?' placeholders
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"table": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Table"
},
"affected_rows": {
"default": 0,
"title": "Affected Rows",
"type": "integer"
}
},
"required": [
"success"
],
"title": "DeleteRowOutput",
"type": "object"
}
```
### Parameters
The table name
Column-value pairs to update
WHERE condition with '?' placeholders
Values matching the '?' placeholders
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"table": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Table"
},
"affected_rows": {
"default": 0,
"title": "Affected Rows",
"type": "integer"
},
"updated_columns": {
"items": {
"type": "string"
},
"title": "Updated Columns",
"type": "array"
}
},
"required": [
"success"
],
"title": "UpdateRowOutput",
"type": "object"
}
```
### Parameters
The table name
Column to filter by
=, >, >=, <, !=, <=, LIKE (Default: `=`)
Value to compare against
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"table": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Table"
},
"row_count": {
"default": 0,
"title": "Row Count",
"type": "integer"
},
"data": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Data",
"type": "array"
}
},
"required": [
"success"
],
"title": "FindRowOutput",
"type": "object"
}
```
### Parameters
The table name
WHERE condition with '?' placeholders
Values matching the '?' placeholders
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"table": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Table"
},
"row_count": {
"default": 0,
"title": "Row Count",
"type": "integer"
},
"data": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Data",
"type": "array"
}
},
"required": [
"success"
],
"title": "ExecuteQueryWithConditionOutput",
"type": "object"
}
```
### Parameters
Procedure name (may be qualified 'db.proc')
Procedure parameters
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"procedure": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Procedure"
},
"row_count": {
"default": 0,
"title": "Row Count",
"type": "integer"
},
"data": {
"anyOf": [
{
"items": {
"additionalProperties": true,
"type": "object"
},
"type": "array"
},
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "ExecuteStoredProcedureOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"TableEntry": {
"additionalProperties": false,
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
}
},
"title": "TableEntry",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"database": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Database"
},
"tables": {
"items": {
"$ref": "#/$defs/TableEntry"
},
"title": "Tables",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListTablesOutput",
"type": "object"
}
```
### Parameters
The table name
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"table": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Table"
},
"columns": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Columns",
"type": "array"
},
"column_count": {
"default": 0,
"title": "Column Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "DescribeTableOutput",
"type": "object"
}
```
## Limits & Quotas
- 60s connection timeout.
- Connections are not pooled — opened per call, closed via the
context manager.
- `find_row` operator allowlist: `=`, `>`, `>=`, `<`, `!=`, `<=`,
`LIKE`.
- `aiomysql` is imported lazily so the manifest can be inspected
without the driver installed.
## Related integrations
## Links
- [MySQL](https://www.mysql.com/)
---
# Nasdaq Data Link Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/nasdaq
Access comprehensive financial data from Nasdaq Data Link E360 platform including balance sheets, cash flows, fundamentals, company statistics, and reference data for publicly traded companies.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/nasdaq/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Nasdaq Data Link** to any ModuleX agent or workflow. Read-only access to the Nasdaq Data Link E360 platform via the official ``nasdaqdatalink`` Python SDK. Covers balance sheets, cash flows, company stats, fundamental details/summary, and reference data for publicly traded companies.
**Categories**: Finance & Payments · Finance · Data · Research · Analytics · **Auth**: API Key · **Actions**: 7
## Authentication
### API Key Authentication
Authenticate using your Nasdaq Data Link API key
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Nasdaq Data Link API Key | Your Nasdaq Data Link API key for authentication | Yes | `xxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
Stock ticker symbol (e.g. 'AAPL', 'MSFT')
Bloomberg FIGI identifier (e.g. 'BBG000BPH459')
Calendar date in YYYY-MM-DD format
Dimensional view: MRQ (Quarterly), MRY (Annual), or MRT (Trailing-twelve-months)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"records": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Records",
"type": "array"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "GetBalanceSheetOutput",
"type": "object"
}
```
### Parameters
Stock ticker symbol (e.g. 'AAPL', 'MSFT')
Bloomberg FIGI identifier (e.g. 'BBG000BPH459')
Calendar date in YYYY-MM-DD format
Dimensional view: MRQ (Quarterly), MRY (Annual), or MRT (Trailing-twelve-months)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"records": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Records",
"type": "array"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "GetCashFlowOutput",
"type": "object"
}
```
### Parameters
Stock ticker symbol (e.g. 'AAPL', 'MSFT')
Bloomberg FIGI identifier (e.g. 'BBG000BPH459')
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"records": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Records",
"type": "array"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "GetCompanyStatsOutput",
"type": "object"
}
```
### Parameters
Stock ticker symbol (e.g. 'AAPL', 'MSFT')
Bloomberg FIGI identifier (e.g. 'BBG000BPH459')
Calendar date in YYYY-MM-DD format
Dimensional view: MRQ (Quarterly), MRY (Annual), or MRT (Trailing-twelve-months)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"records": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Records",
"type": "array"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "GetFundamentalDetailsOutput",
"type": "object"
}
```
### Parameters
Stock ticker symbol (e.g. 'AAPL', 'MSFT')
Bloomberg FIGI identifier (e.g. 'BBG000BPH459')
Calendar date in YYYY-MM-DD format
Dimensional view: MRQ (Quarterly), MRY (Annual), or MRT (Trailing-twelve-months)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"records": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Records",
"type": "array"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "GetFundamentalSummaryOutput",
"type": "object"
}
```
### Parameters
Stock ticker symbol (e.g. 'AAPL', 'MSFT')
Bloomberg FIGI identifier (e.g. 'BBG000BPH459')
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"records": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Records",
"type": "array"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
}
},
"required": [
"success"
],
"title": "GetReferenceDataOutput",
"type": "object"
}
```
### Parameters
Table type to list fields for: 'balance_sheet', 'cash_flow', 'company_stats', 'fundamental_details', 'fundamental_summary', 'reference_data'
### Response
```json
{
"$defs": {
"NasdaqField": {
"additionalProperties": false,
"properties": {
"name": {
"title": "Name",
"type": "string"
},
"description": {
"title": "Description",
"type": "string"
},
"type": {
"title": "Type",
"type": "string"
},
"filterable": {
"default": false,
"title": "Filterable",
"type": "boolean"
}
},
"required": [
"name",
"description",
"type"
],
"title": "NasdaqField",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"table_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Table Type"
},
"fields": {
"items": {
"$ref": "#/$defs/NasdaqField"
},
"title": "Fields",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListAvailableFieldsOutput",
"type": "object"
}
```
## Limits & Quotas
- Subscription-gated. E360 endpoints require an active Nasdaq Data
Link subscription on the NDAQ table family.
- DataFrame results are converted to JSON-safe lists of dicts
(`NaN` → `None`). Empty DataFrames return `records=[]` with a
`message: "No data found..."` (matches legacy).
- Lazy SDK import — if `nasdaq-data-link` isn't installed, every
table-query tool degrades to `success=False` with an "install
with: pip install nasdaq-data-link" error.
## Related integrations
## Links
- [Nasdaq Data Link](https://data.nasdaq.com)
---
# Netlify Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/netlify
Web hosting and automation platform for modern web projects
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/netlify/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Netlify** to any ModuleX agent or workflow. Web hosting and automation platform for modern web projects, interfacing with the Netlify REST API (`api.netlify.com/api/v1`).
**Categories**: Developer Tools & Infrastructure · Hosting · Ci Cd · **Auth**: OAuth2 · **Actions**: 4
## Authentication
### OAuth2 Authentication
Connect using Netlify OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Netlify OAuth App Client ID | Yes | `-` |
| Client Secret | Netlify OAuth App Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://app.netlify.com/authorize`
- **Token URL**: `https://api.netlify.com/oauth/token`
## Available Actions
### Parameters
The Netlify site ID to retrieve information for
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"ssl_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ssl Url"
},
"admin_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Admin Url"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"default_domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Default Domain"
},
"custom_domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Custom Domain"
}
},
"required": [
"success"
],
"title": "GetSiteOutput",
"type": "object"
}
```
### Parameters
The Netlify site ID to list files for
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"files": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Files",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListFilesOutput",
"type": "object"
}
```
### Parameters
The Netlify site ID to list deploys for
Maximum number of deploys to return
Maximum number of pages to fetch (1-500) (Default: `50`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"deploys": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Deploys",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListSiteDeploysOutput",
"type": "object"
}
```
### Parameters
The Netlify site ID to rollback a deploy for
The deploy ID to restore
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"ssl_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Ssl Url"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"required": [
"success"
],
"title": "RollbackDeployOutput",
"type": "object"
}
```
## Limits & Quotas
- Netlify API rate limit: 500 requests per minute per access token (as documented by Netlify).
- Non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
- Deploy operations (rollback) may take a few seconds to propagate.
## Related integrations
## Links
- [Netlify](https://www.netlify.com)
---
# NeverBounce Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/neverbounce
Integrate NeverBounce to verify email deliverability in real time — classify addresses as valid, invalid, catch-all, disposable, or unknown — and check your remaining verification credits.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/neverbounce/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **NeverBounce** to any ModuleX agent or workflow. Real-time email verification and account credit lookup against the NeverBounce v4 REST API (`api.neverbounce.com/v4`). Classifies an address as valid, invalid, catch-all, disposable, or unknown and surfaces role-account and free-provider flags.
**Categories**: Sales · Enrichment · Sales Engagement · **Auth**: API Key · **Actions**: 2
## Authentication
### API Key Authentication
Authenticate using your NeverBounce API key
Go to https://app.neverbounce.com and sign up or log in
Open Settings and select the 'API' section
Create a new API key or copy your existing one
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| NeverBounce API Key | Your NeverBounce API key from app.neverbounce.com | Yes | `secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
Email address to verify (e.g., john@example.com)
### Response
```json
{
"additionalProperties": false,
"description": "Result of verifying a single email address.",
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"deliverable": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Deliverable"
},
"role_account": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Role Account"
},
"free_email": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Free Email"
},
"did_you_mean": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Did You Mean"
},
"flags": {
"items": {
"type": "string"
},
"title": "Flags",
"type": "array"
},
"result": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "VerifyEmailOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"description": "Remaining verification credits for the account.",
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"credits": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Credits"
},
"free_credits": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Free Credits"
}
},
"required": [
"success"
],
"title": "GetCreditsOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limit**: ~60 requests/min on standard plans.
- **Credits**: each `verify_email` call consumes one verification
credit; `get_credits` is free and does not consume credits.
- **Error model**: the v4 API returns HTTP 200 even for API-level
failures and signals the outcome via the response envelope's
`status` field. A non-`"success"` status, a non-2xx HTTP response,
or a timeout is caught and returned as `success=False` + `error`
rather than raising. Plan for retries on the agent side based on the
error string.
## Related integrations
## Links
- [NeverBounce](https://www.neverbounce.com)
---
# New Relic Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/new-relic
Integrate New Relic into workflows. Run NRQL queries, search monitored entities, fetch entity details, and record deployment change events via the NerdGraph GraphQL API.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/new_relic/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **New Relic** to any ModuleX agent or workflow. Query observability data and record deployments in New Relic. Run NRQL queries, search monitored entities, fetch entity details, and create deployment change events through New Relic's NerdGraph GraphQL API (`api.newrelic.com/graphql`, or `api.eu.newrelic.com/graphql` for the EU region).
**Categories**: Monitoring & Observability · Monitoring · Observability · **Auth**: API Key · **Actions**: 4
## Authentication
### API Key Authentication
Authenticate using your New Relic user API key
Sign in to New Relic at https://one.newrelic.com
Open the user menu and go to 'API keys'
Create a new 'User' key (its value starts with 'NRAK-')
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| New Relic User API Key | Your New Relic user API key (starts with 'NRAK-') | Yes | `NRAK-` |
## Available Actions
### Parameters
New Relic account ID to query
NRQL query to execute
New Relic data center region: 'us' (default) or 'eu' (Default: `us`)
Optional query timeout in seconds
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"results": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Results",
"type": "array"
},
"result_count": {
"default": 0,
"title": "Result Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "NrqlQueryOutput",
"type": "object"
}
```
### Parameters
Entity search query, e.g. name like "api" or domainType = "APM-APPLICATION"
New Relic data center region: 'us' (default) or 'eu' (Default: `us`)
Pagination cursor from a previous entity search
### Response
```json
{
"$defs": {
"Entity": {
"additionalProperties": false,
"description": "A single monitored New Relic entity (guid, name, entityType).",
"properties": {
"guid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Guid"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"entity_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Entity Type"
}
},
"title": "Entity",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Query"
},
"entities": {
"items": {
"$ref": "#/$defs/Entity"
},
"title": "Entities",
"type": "array"
},
"next_cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Cursor"
}
},
"required": [
"success"
],
"title": "SearchEntitiesOutput",
"type": "object"
}
```
### Parameters
Entity GUID
New Relic data center region: 'us' (default) or 'eu' (Default: `us`)
### Response
```json
{
"$defs": {
"Entity": {
"additionalProperties": false,
"description": "A single monitored New Relic entity (guid, name, entityType).",
"properties": {
"guid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Guid"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"entity_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Entity Type"
}
},
"title": "Entity",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"entity": {
"anyOf": [
{
"$ref": "#/$defs/Entity"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetEntityOutput",
"type": "object"
}
```
### Parameters
GUID of the entity associated with the deployment
Deployment version, release name, or commit SHA
New Relic data center region: 'us' (default) or 'eu' (Default: `us`)
Short description of the deployment
Longer deployment description
Deployment changelog text or URL
Commit SHA or identifier associated with the deployment
URL to the deployment, build, or release details
User or automation that performed the deployment
Optional group ID to correlate related changes
Custom change event metadata as key-value pairs with string, number, or boolean values
Deployment type: 'basic', 'blue green', 'canary', 'rolling', or 'shadow' (Default: `basic`)
Event timestamp in milliseconds since Unix epoch
### Response
```json
{
"$defs": {
"ChangeTrackingEntity": {
"additionalProperties": false,
"description": "The entity a change tracking event is associated with.",
"properties": {
"guid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Guid"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
}
},
"title": "ChangeTrackingEntity",
"type": "object"
},
"ChangeTrackingEvent": {
"additionalProperties": false,
"description": "A created New Relic change tracking (deployment) event.",
"properties": {
"category": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Category"
},
"category_and_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Category And Type"
},
"change_tracking_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Change Tracking Id"
},
"custom_attributes": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Custom Attributes"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"group_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Group Id"
},
"short_description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Short Description"
},
"timestamp": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"user": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "User"
},
"entity": {
"anyOf": [
{
"$ref": "#/$defs/ChangeTrackingEntity"
},
{
"type": "null"
}
],
"default": null
}
},
"title": "ChangeTrackingEvent",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"event": {
"anyOf": [
{
"$ref": "#/$defs/ChangeTrackingEvent"
},
{
"type": "null"
}
],
"default": null
},
"messages": {
"items": {
"type": "string"
},
"title": "Messages",
"type": "array"
}
},
"required": [
"success"
],
"title": "CreateDeploymentEventOutput",
"type": "object"
}
```
## Limits & Quotas
- All actions hit the NerdGraph GraphQL endpoint; New Relic enforces
account-level NerdGraph rate limits (per-minute request and query-cost
budgets). Heavy or unbounded NRQL queries may be throttled or time out.
- `nrql_query` accepts an optional `timeout` (seconds) forwarded to
NerdGraph; the HTTP client itself caps each call at 90 seconds.
- `create_deployment_event` custom attribute names must be letters,
numbers, and underscores (not starting with a number), must not contain
`.`, and must avoid New Relic's reserved NRQL keywords; invalid names are
rejected before the call. A supplied `timestamp` must be within one day
of the current time per New Relic's change tracking rules.
- **Error model**: non-2xx responses, GraphQL `errors`, and timeouts are
caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [New Relic](https://newrelic.com)
---
# Notion Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/notion
Notion workspace integration: pages, databases, blocks, users, comments, and search.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/notion/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Notion** to any ModuleX agent or workflow. Notion v1 REST API integration. Pure HTTP (no SDK dep). 19 actions across pages, databases, blocks, users, comments, and search.
**Categories**: Productivity & Collaboration · Productivity · Knowledge Management · Documentation · **Auth**: OAuth2 (Recommended), Internal Integration · **Actions**: 19
## Authentication
### OAuth2 (Recommended)
Connect using Notion OAuth — most secure option
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Notion OAuth integration Client ID | Yes | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
| Client Secret | Notion OAuth integration Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://api.notion.com/v1/oauth/authorize`
- **Token URL**: `https://api.notion.com/v1/oauth/token`
### Internal Integration
Connect using a Notion Internal Integration Token
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Internal Integration Token | Notion Internal Integration secret | Yes | `secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
Search query text
Filter (e.g. {'property': 'object', 'value': 'page'})
Sort options
Pagination cursor
Number of results (max 100) (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
},
"has_more": {
"default": false,
"title": "Has More",
"type": "boolean"
},
"next_cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Cursor"
},
"results": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Results",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchOutput",
"type": "object"
}
```
### Parameters
'database' or 'page'
Parent page/database ID
Page title
Markdown content (converted to paragraph blocks)
Direct Notion block array (overrides content)
Database properties (required for database parents)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created Time"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"properties": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Properties"
},
"parent": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Parent"
}
},
"required": [
"success"
],
"title": "CreatePageOutput",
"type": "object"
}
```
### Parameters
Page ID to retrieve
Include page child blocks (N+1 fetch) (Default: `true`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created Time"
},
"last_edited_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Edited Time"
},
"created_by": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Created By"
},
"last_edited_by": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Edited By"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"properties": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Properties"
},
"parent": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Parent"
},
"archived": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Archived"
},
"content": {
"anyOf": [
{
"items": {
"additionalProperties": true,
"type": "object"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Content"
}
},
"required": [
"success"
],
"title": "GetPageOutput",
"type": "object"
}
```
### Parameters
Page ID
New title
Updated properties
Archive (true) / unarchive (false)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"last_edited_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Edited Time"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"properties": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Properties"
},
"archived": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Archived"
}
},
"required": [
"success"
],
"title": "UpdatePageOutput",
"type": "object"
}
```
### Parameters
Database ID
Filter conditions
Sort options
Pagination cursor
Number of results (max 100) (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
},
"has_more": {
"default": false,
"title": "Has More",
"type": "boolean"
},
"next_cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Cursor"
},
"database_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Database Id"
},
"results": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Results",
"type": "array"
}
},
"required": [
"success"
],
"title": "QueryDatabaseOutput",
"type": "object"
}
```
### Parameters
Database ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created Time"
},
"last_edited_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Edited Time"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"properties": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Properties"
},
"parent": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Parent"
},
"archived": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Archived"
},
"is_inline": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Is Inline"
}
},
"required": [
"success"
],
"title": "GetDatabaseOutput",
"type": "object"
}
```
### Parameters
Parent page ID
Database title
Property schema definitions
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created Time"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"properties": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Properties"
},
"parent": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Parent"
}
},
"required": [
"success"
],
"title": "CreateDatabaseOutput",
"type": "object"
}
```
### Parameters
Database ID
New title
New description
Updated property schema
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"last_edited_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Edited Time"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"properties": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Properties"
}
},
"required": [
"success"
],
"title": "UpdateDatabaseOutput",
"type": "object"
}
```
### Parameters
Database ID
Item properties matching database schema
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created Time"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"properties": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Properties"
}
},
"required": [
"success"
],
"title": "CreateDatabaseItemOutput",
"type": "object"
}
```
### Parameters
Block ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created Time"
},
"last_edited_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Edited Time"
},
"has_children": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has Children"
},
"archived": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Archived"
},
"parent": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Parent"
},
"content": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Content"
}
},
"required": [
"success"
],
"title": "GetBlockOutput",
"type": "object"
}
```
### Parameters
Parent block or page ID
Pagination cursor
Number of results (max 100) (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
},
"has_more": {
"default": false,
"title": "Has More",
"type": "boolean"
},
"next_cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Cursor"
},
"block_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Block Id"
},
"children": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Children",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetBlockChildrenOutput",
"type": "object"
}
```
### Parameters
Block / page ID to append into
Notion block objects to append
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"block_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Block Id"
},
"appended_blocks": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Appended Blocks",
"type": "array"
},
"total_appended": {
"default": 0,
"title": "Total Appended",
"type": "integer"
}
},
"required": [
"success"
],
"title": "AppendBlocksOutput",
"type": "object"
}
```
### Parameters
Block ID
Block object with updated content
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"last_edited_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Edited Time"
},
"has_children": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has Children"
},
"content": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Content"
}
},
"required": [
"success"
],
"title": "UpdateBlockOutput",
"type": "object"
}
```
### Parameters
Block ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"archived": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Archived"
}
},
"required": [
"success"
],
"title": "DeleteBlockOutput",
"type": "object"
}
```
### Parameters
Pagination cursor
Number of results (max 100) (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
},
"has_more": {
"default": false,
"title": "Has More",
"type": "boolean"
},
"next_cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Cursor"
},
"users": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Users",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListUsersOutput",
"type": "object"
}
```
### Parameters
User ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"object": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Object"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"avatar_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Avatar Url"
},
"person": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Person"
},
"bot": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Bot"
}
},
"required": [
"success"
],
"title": "GetUserOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"object": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Object"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"avatar_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Avatar Url"
},
"bot": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Bot"
}
},
"required": [
"success"
],
"title": "GetBotUserOutput",
"type": "object"
}
```
### Parameters
Rich text array for the comment body
Page ID (use this for new comments)
Discussion ID (use this for replies)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created Time"
},
"discussion_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Discussion Id"
},
"parent": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Parent"
},
"rich_text": {
"anyOf": [
{
"items": {
"additionalProperties": true,
"type": "object"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Rich Text"
},
"created_by": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Created By"
}
},
"required": [
"success"
],
"title": "CreateCommentOutput",
"type": "object"
}
```
### Parameters
Block / page ID
Pagination cursor
Number of results (max 100) (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
},
"has_more": {
"default": false,
"title": "Has More",
"type": "boolean"
},
"next_cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Next Cursor"
},
"block_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Block Id"
},
"comments": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Comments",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetCommentsOutput",
"type": "object"
}
```
## Limits & Quotas
- 30s timeout on every request.
- `page_size` clamped to 100 (Notion's max).
- All actions wrap in try/except → `success=False` envelope
(exa-style).
- Trivial markdown→blocks conversion in `create_page.content`:
splits on newlines and creates one paragraph block per non-empty
line. Use `children` for anything fancier.
## Related integrations
## Links
- [Notion](https://www.notion.so)
---
# NPM Registry Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/npm
Access the npm registry to search packages, get package information, versions, dependencies, and download statistics
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/npm/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **NPM Registry** to any ModuleX agent or workflow. Read-only access to the public npm registry: package info, search, popular packages, version history, dependency graphs, and download statistics.
**Categories**: Developer Tools & Infrastructure · Coding · Package Management · Developer Tools · **Auth**: API Key · **Actions**: 6
## Authentication
### API Key Authentication
Optional authentication for private npm registries. Leave empty for public npm registry access.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| NPM API Key | Your npm authentication token (optional for public registry) | No | `-` |
## Available Actions
### Parameters
The name of the npm package to look up
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"version": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Version"
},
"description": {
"default": "",
"title": "Description",
"type": "string"
},
"author": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Author"
},
"homepage": {
"default": "",
"title": "Homepage",
"type": "string"
},
"repository": {
"default": "",
"title": "Repository",
"type": "string"
},
"license": {
"default": "",
"title": "License",
"type": "string"
},
"keywords": {
"items": {
"type": "string"
},
"title": "Keywords",
"type": "array"
},
"dependencies": {
"additionalProperties": {
"type": "string"
},
"title": "Dependencies",
"type": "object"
},
"devDependencies": {
"additionalProperties": {
"type": "string"
},
"title": "Devdependencies",
"type": "object"
},
"peerDependencies": {
"additionalProperties": {
"type": "string"
},
"title": "Peerdependencies",
"type": "object"
}
},
"required": [
"success"
],
"title": "GetPackageInfoOutput",
"type": "object"
}
```
### Parameters
Search query text
Number of results to return (1-250) (Default: `10`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
},
"packages": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Packages",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchPackagesOutput",
"type": "object"
}
```
### Parameters
Number of popular packages to return (1-250) (Default: `10`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"packages": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Packages",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetPopularPackagesOutput",
"type": "object"
}
```
### Parameters
The name of the npm package
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"dist_tags": {
"additionalProperties": {
"type": "string"
},
"title": "Dist Tags",
"type": "object"
},
"versions": {
"items": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"title": "Versions",
"type": "array"
},
"total_versions": {
"default": 0,
"title": "Total Versions",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetPackageVersionsOutput",
"type": "object"
}
```
### Parameters
The name of the npm package
Specific version (defaults to latest)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"version": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Version"
},
"dependencies": {
"additionalProperties": {
"type": "string"
},
"title": "Dependencies",
"type": "object"
},
"devDependencies": {
"additionalProperties": {
"type": "string"
},
"title": "Devdependencies",
"type": "object"
},
"peerDependencies": {
"additionalProperties": {
"type": "string"
},
"title": "Peerdependencies",
"type": "object"
},
"optionalDependencies": {
"additionalProperties": {
"type": "string"
},
"title": "Optionaldependencies",
"type": "object"
}
},
"required": [
"success"
],
"title": "GetPackageDependenciesOutput",
"type": "object"
}
```
### Parameters
The name of the npm package
Time period for download statistics (Default: `last-week`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"package": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Package"
},
"period": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Period"
},
"start": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Start"
},
"end": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "End"
},
"total_downloads": {
"default": 0,
"title": "Total Downloads",
"type": "integer"
},
"daily_downloads": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Daily Downloads",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetPackageDownloadStatsOutput",
"type": "object"
}
```
## Limits & Quotas
- npm's public registry has loose, unenforced limits — be reasonable.
Two API hosts are involved: `registry.npmjs.org` (metadata) and
`api.npmjs.org` (downloads).
- `period` must be one of `last-day`, `last-week`, `last-month`,
`last-year` (validated client-side; otherwise `success=False`).
- Search `size` is clamped to [1, 250].
## Related integrations
## Links
---
# Obsidian Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/obsidian
Read, create, update, search, and delete notes in your Obsidian vault. Manage periodic notes, execute commands, and patch content at specific locations. Requires the Obsidian Local REST API plugin.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/obsidian/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Obsidian** to any ModuleX agent or workflow. Read, create, update, search, and delete notes in your Obsidian vault via the [Obsidian Local REST API](https://obsidian.md) plugin. Manage periodic notes, list and execute commands, work with the active file, and patch content at specific headings, block references, or frontmatter fields. The plugin runs locally inside your Obsidian app and is reachable at a `base_url` you pass on every call (default `https://127.0.0.1:27124`). Because the plugin serves a self-signed TLS certificate, the HTTP client does not verify the certificate chain.
**Categories**: Productivity & Collaboration · Note Taking · Knowledge Base · **Auth**: API Key · **Actions**: 15
## Authentication
### API Key Authentication
Authenticate using the API key from the Obsidian Local REST API plugin
Install the 'Local REST API' community plugin in Obsidian
Open the plugin settings and enable it
Copy the API key shown in the plugin settings
Note the server URL (default https://127.0.0.1:27124) for the base_url parameter
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Obsidian Local REST API Key | API key from the Obsidian Local REST API plugin settings | Yes | `-` |
## Available Actions
### Parameters
Base URL for the Obsidian Local REST API (e.g. https://127.0.0.1:27124)
Directory path relative to vault root. Leave empty to list the root.
### Response
```json
{
"$defs": {
"FileEntry": {
"additionalProperties": false,
"description": "A single file or directory entry in ``list_files``.",
"properties": {
"path": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Path"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
}
},
"title": "FileEntry",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"files": {
"items": {
"$ref": "#/$defs/FileEntry"
},
"title": "Files",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListFilesOutput",
"type": "object"
}
```
### Parameters
Base URL for the Obsidian Local REST API (e.g. https://127.0.0.1:27124)
Path to the note relative to vault root (e.g. "folder/note.md")
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"content": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content"
},
"filename": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Filename"
}
},
"required": [
"success"
],
"title": "GetNoteOutput",
"type": "object"
}
```
### Parameters
Base URL for the Obsidian Local REST API (e.g. https://127.0.0.1:27124)
Path for the note relative to vault root (e.g. "folder/note.md")
Markdown content for the note
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"filename": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Filename"
},
"created": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
}
},
"required": [
"success"
],
"title": "CreateNoteOutput",
"type": "object"
}
```
### Parameters
Base URL for the Obsidian Local REST API (e.g. https://127.0.0.1:27124)
Path to the note relative to vault root (e.g. "folder/note.md")
Markdown content to append to the note
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"filename": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Filename"
},
"appended": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Appended"
}
},
"required": [
"success"
],
"title": "AppendNoteOutput",
"type": "object"
}
```
### Parameters
Base URL for the Obsidian Local REST API (e.g. https://127.0.0.1:27124)
Path to the note relative to vault root (e.g. "folder/note.md")
Content to insert at the target location
How to insert content: append, prepend, or replace
Type of target: heading, block, or frontmatter
Target identifier (heading text, block reference ID, or frontmatter field name)
Delimiter for nested headings (default: "::")
Whether to trim whitespace from target before matching
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"filename": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Filename"
},
"patched": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Patched"
}
},
"required": [
"success"
],
"title": "PatchNoteOutput",
"type": "object"
}
```
### Parameters
Base URL for the Obsidian Local REST API (e.g. https://127.0.0.1:27124)
Path to the note to delete relative to vault root
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"filename": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Filename"
},
"deleted": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted"
}
},
"required": [
"success"
],
"title": "DeleteNoteOutput",
"type": "object"
}
```
### Parameters
Base URL for the Obsidian Local REST API (e.g. https://127.0.0.1:27124)
Text to search for across vault notes
Number of characters of context around each match (default: 100)
### Response
```json
{
"$defs": {
"SearchMatch": {
"additionalProperties": false,
"description": "A single matching context snippet within a search result.",
"properties": {
"context": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Context"
}
},
"title": "SearchMatch",
"type": "object"
},
"SearchResultItem": {
"additionalProperties": false,
"description": "A single result row in ``search``.",
"properties": {
"filename": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Filename"
},
"score": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Score"
},
"matches": {
"items": {
"$ref": "#/$defs/SearchMatch"
},
"title": "Matches",
"type": "array"
}
},
"title": "SearchResultItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"results": {
"items": {
"$ref": "#/$defs/SearchResultItem"
},
"title": "Results",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchOutput",
"type": "object"
}
```
### Parameters
Base URL for the Obsidian Local REST API (e.g. https://127.0.0.1:27124)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"content": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content"
},
"filename": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Filename"
}
},
"required": [
"success"
],
"title": "GetActiveOutput",
"type": "object"
}
```
### Parameters
Base URL for the Obsidian Local REST API (e.g. https://127.0.0.1:27124)
Markdown content to append to the active file
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"appended": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Appended"
}
},
"required": [
"success"
],
"title": "AppendActiveOutput",
"type": "object"
}
```
### Parameters
Base URL for the Obsidian Local REST API (e.g. https://127.0.0.1:27124)
Content to insert at the target location
How to insert content: append, prepend, or replace
Type of target: heading, block, or frontmatter
Target identifier (heading text, block reference ID, or frontmatter field name)
Delimiter for nested headings (default: "::")
Whether to trim whitespace from target before matching
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"patched": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Patched"
}
},
"required": [
"success"
],
"title": "PatchActiveOutput",
"type": "object"
}
```
### Parameters
Base URL for the Obsidian Local REST API (e.g. https://127.0.0.1:27124)
Path to the file relative to vault root
Whether to open the file in a new leaf/tab
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"filename": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Filename"
},
"opened": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Opened"
}
},
"required": [
"success"
],
"title": "OpenFileOutput",
"type": "object"
}
```
### Parameters
Base URL for the Obsidian Local REST API (e.g. https://127.0.0.1:27124)
### Response
```json
{
"$defs": {
"CommandItem": {
"additionalProperties": false,
"description": "A single available command in ``list_commands``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
}
},
"title": "CommandItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"commands": {
"items": {
"$ref": "#/$defs/CommandItem"
},
"title": "Commands",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListCommandsOutput",
"type": "object"
}
```
### Parameters
Base URL for the Obsidian Local REST API (e.g. https://127.0.0.1:27124)
ID of the command to execute (use list_commands to discover available commands)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"command_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Command Id"
},
"executed": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Executed"
}
},
"required": [
"success"
],
"title": "ExecuteCommandOutput",
"type": "object"
}
```
### Parameters
Base URL for the Obsidian Local REST API (e.g. https://127.0.0.1:27124)
Period type: daily, weekly, monthly, quarterly, or yearly
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"content": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Content"
},
"period": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Period"
}
},
"required": [
"success"
],
"title": "GetPeriodicNoteOutput",
"type": "object"
}
```
### Parameters
Base URL for the Obsidian Local REST API (e.g. https://127.0.0.1:27124)
Period type: daily, weekly, monthly, quarterly, or yearly
Markdown content to append to the periodic note
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"period": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Period"
},
"appended": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Appended"
}
},
"required": [
"success"
],
"title": "AppendPeriodicNoteOutput",
"type": "object"
}
```
## Limits & Quotas
- The Local REST API runs on the user's own machine, so throughput is
bound only by the local Obsidian instance; there is no vendor rate
limit.
- `base_url` must be reachable from where the runtime executes
(typically the same host). The default `https://127.0.0.1:27124` only
works for a co-located process.
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Obsidian](https://obsidian.md)
---
# Okta Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/okta
Manage users and user-type metadata in an Okta tenant via the Okta Management REST API (``/api/v1`` under your Okta subdomain).
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/okta/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Okta** to any ModuleX agent or workflow. Manage users and user-type metadata in an Okta tenant via the Okta Management REST API (`https://.okta.com/api/v1`).
**Categories**: Developer Tools & Infrastructure · Identity & Access Management · Productivity & Collaboration · **Auth**: Okta API Token · **Actions**: 4
## Authentication
### Okta API Token
Authenticate with an Okta SSWS API token plus the tenant subdomain. The token is sent as ``Authorization: SSWS <token>`` and the subdomain is used to build the request host (``https://<subdomain>.okta.com``).
Sign in to your Okta admin console.
Open Security -> API -> Tokens, then click Create Token.
Copy the generated SSWS token (it is shown only once).
Your subdomain is the leading part of your admin URL, e.g. for ``acme.okta.com`` the subdomain is ``acme``.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Okta Subdomain | The tenant subdomain (e.g. ``acme`` for ``acme.okta.com``). Do not include ``.okta.com``. | Yes | `acme` |
| Okta API Token | Your SSWS API token from Okta admin (Security -> API -> Tokens). | Yes | `00xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
The first name of the user.
The last name of the user.
The email address of the user.
The login (typically the email) for the user.
Optional mobile phone number for the user.
Optional ID of a non-default user type. Use list_type_id_options to enumerate available IDs.
Whether to execute the activation lifecycle on creation. Defaults to true. (Default: `true`)
### Response
```json
{
"$defs": {
"UserResource": {
"additionalProperties": false,
"description": "An Okta user as returned by /users endpoints.\n\nField set is intentionally permissive — Okta returns many fields; we\nexpose the ones agents commonly need and let the rest live in ``profile``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"activated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Activated"
},
"statusChanged": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Statuschanged"
},
"lastLogin": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lastlogin"
},
"lastUpdated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lastupdated"
},
"passwordChanged": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Passwordchanged"
},
"type": {
"anyOf": [
{
"$ref": "#/$defs/UserTypeRef"
},
{
"type": "null"
}
],
"default": null
},
"profile": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Profile"
},
"credentials": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Credentials"
}
},
"title": "UserResource",
"type": "object"
},
"UserTypeRef": {
"additionalProperties": false,
"description": "Reference to a user type returned alongside a user resource.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
}
},
"title": "UserTypeRef",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"user": {
"anyOf": [
{
"$ref": "#/$defs/UserResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateUserOutput",
"type": "object"
}
```
### Parameters
The unique identifier of the user (Okta user ID, login, or email).
### Response
```json
{
"$defs": {
"UserResource": {
"additionalProperties": false,
"description": "An Okta user as returned by /users endpoints.\n\nField set is intentionally permissive — Okta returns many fields; we\nexpose the ones agents commonly need and let the rest live in ``profile``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"activated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Activated"
},
"statusChanged": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Statuschanged"
},
"lastLogin": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lastlogin"
},
"lastUpdated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lastupdated"
},
"passwordChanged": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Passwordchanged"
},
"type": {
"anyOf": [
{
"$ref": "#/$defs/UserTypeRef"
},
{
"type": "null"
}
],
"default": null
},
"profile": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Profile"
},
"credentials": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Credentials"
}
},
"title": "UserResource",
"type": "object"
},
"UserTypeRef": {
"additionalProperties": false,
"description": "Reference to a user type returned alongside a user resource.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
}
},
"title": "UserTypeRef",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"user": {
"anyOf": [
{
"$ref": "#/$defs/UserResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetUserOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"TypeIdOption": {
"additionalProperties": false,
"description": "One row from the dropdown returned by list_type_id_options.",
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Label"
},
"value": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
}
},
"title": "TypeIdOption",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"options": {
"items": {
"$ref": "#/$defs/TypeIdOption"
},
"title": "Options",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListTypeIdOptionsOutput",
"type": "object"
}
```
### Parameters
The unique identifier of the user to update.
New first name for the user.
New last name for the user.
New email address for the user.
New login for the user.
New mobile phone number for the user.
Optional new user type ID. Use list_type_id_options to discover valid IDs.
### Response
```json
{
"$defs": {
"UserResource": {
"additionalProperties": false,
"description": "An Okta user as returned by /users endpoints.\n\nField set is intentionally permissive — Okta returns many fields; we\nexpose the ones agents commonly need and let the rest live in ``profile``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"created": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"activated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Activated"
},
"statusChanged": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Statuschanged"
},
"lastLogin": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lastlogin"
},
"lastUpdated": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Lastupdated"
},
"passwordChanged": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Passwordchanged"
},
"type": {
"anyOf": [
{
"$ref": "#/$defs/UserTypeRef"
},
{
"type": "null"
}
],
"default": null
},
"profile": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Profile"
},
"credentials": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Credentials"
}
},
"title": "UserResource",
"type": "object"
},
"UserTypeRef": {
"additionalProperties": false,
"description": "Reference to a user type returned alongside a user resource.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
}
},
"title": "UserTypeRef",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"user": {
"anyOf": [
{
"$ref": "#/$defs/UserResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UpdateUserOutput",
"type": "object"
}
```
## Limits & Quotas
- Okta enforces per-org rate limits that vary by endpoint and plan; common
defaults are 600 requests/minute for the Users endpoints on developer orgs
and higher on production tiers. See
https://developer.okta.com/docs/reference/rl-global-mgmt/.
- Each response includes `X-Rate-Limit-Limit`, `X-Rate-Limit-Remaining`, and
`X-Rate-Limit-Reset` headers; agents that hit `429` should back off until
the reset epoch.
- `update_user` issues one `GET` plus one `PUT` per call (the existing profile
is merged client-side so partial updates do not blank out fields).
- **Error model**: non-2xx responses and timeouts are caught and returned as
`success=False` + `error` rather than raising.
## Related integrations
## Links
- [Okta](https://www.okta.com)
---
# PagerDuty Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/pagerduty
Incident management and on-call scheduling platform
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/pagerduty/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **PagerDuty** to any ModuleX agent or workflow. Incident management, on-call scheduling, and alerting via the PagerDuty REST API (`api.pagerduty.com`).
**Categories**: Monitoring & Observability · Incident Management · Developer Tools & Infrastructure · **Auth**: OAuth2 · **Actions**: 4
## Authentication
### OAuth2 Authentication
Connect using PagerDuty OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | PagerDuty OAuth App Client ID | Yes | `-` |
| Client Secret | PagerDuty OAuth App Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://identity.pagerduty.com/oauth/authorize`
- **Token URL**: `https://identity.pagerduty.com/oauth/token`
- **Scopes**: `read`, `write`
## Available Actions
### Parameters
A succinct description of the nature, symptoms, cause, or effect of the incident
The ID of the PagerDuty service to trigger the incident on
The urgency of the incident: high or low
Additional incident details
A string which identifies the incident. Subsequent requests with the same key and service will be rejected if an open incident matches
The ID of the escalation policy to assign
List of user IDs to assign to the incident
Phone number for the conference bridge (format: +1 415-555-1212,,,,1234#)
URL for the conference bridge (e.g. a web conference or Slack channel link)
### Response
```json
{
"$defs": {
"IncidentSummary": {
"additionalProperties": false,
"description": "Core fields returned for an incident by the PagerDuty API.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"urgency": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Urgency"
},
"incident_key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Incident Key"
},
"html_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Html Url"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"service": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Service"
},
"escalation_policy": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Escalation Policy"
},
"assignments": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Assignments",
"type": "array"
}
},
"title": "IncidentSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"incident": {
"anyOf": [
{
"$ref": "#/$defs/IncidentSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "TriggerIncidentOutput",
"type": "object"
}
```
### Parameters
The ID of the incident to acknowledge
### Response
```json
{
"$defs": {
"IncidentSummary": {
"additionalProperties": false,
"description": "Core fields returned for an incident by the PagerDuty API.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"urgency": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Urgency"
},
"incident_key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Incident Key"
},
"html_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Html Url"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"service": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Service"
},
"escalation_policy": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Escalation Policy"
},
"assignments": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Assignments",
"type": "array"
}
},
"title": "IncidentSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"incident": {
"anyOf": [
{
"$ref": "#/$defs/IncidentSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "AcknowledgeIncidentOutput",
"type": "object"
}
```
### Parameters
The ID of the incident to resolve
### Response
```json
{
"$defs": {
"IncidentSummary": {
"additionalProperties": false,
"description": "Core fields returned for an incident by the PagerDuty API.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Summary"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"urgency": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Urgency"
},
"incident_key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Incident Key"
},
"html_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Html Url"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"service": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Service"
},
"escalation_policy": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Escalation Policy"
},
"assignments": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Assignments",
"type": "array"
}
},
"title": "IncidentSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"incident": {
"anyOf": [
{
"$ref": "#/$defs/IncidentSummary"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "ResolveIncidentOutput",
"type": "object"
}
```
### Parameters
The ID of the on-call schedule
The ID of the user to search for in the schedule
### Response
```json
{
"$defs": {
"OncallUser": {
"additionalProperties": false,
"description": "A user found on-call for a schedule.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
},
"html_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Html Url"
}
},
"title": "OncallUser",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"found": {
"default": false,
"title": "Found",
"type": "boolean"
},
"user": {
"anyOf": [
{
"$ref": "#/$defs/OncallUser"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "FindOncallUserOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limits**: PagerDuty REST API allows up to 960 requests per minute (varies by account tier).
- **Throttling**: Requests exceeding the rate limit receive HTTP 429; implement client-side backoff.
- **Error model**: non-2xx responses raise `httpx.HTTPStatusError` (Pattern A). The caller should handle retries.
## Related integrations
## Links
- [PagerDuty](https://www.pagerduty.com)
---
# Pinterest Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/pinterest
Visual discovery and social media platform for managing boards, pins, and content. Create pins, organize boards, and manage visual content for marketing and inspiration.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/pinterest/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Pinterest** to any ModuleX agent or workflow. Manage boards, board sections, and pins via the Pinterest REST API v5.
**Categories**: Social Media · Marketing & Email · Social Media · Automation · Development · Miscellaneous · Pinterest · **Auth**: OAuth Access Token, OAuth 2.0 · **Actions**: 4
## Authentication
### OAuth Access Token
Authenticate using your Pinterest OAuth access token. The token can be obtained through Pinterest's OAuth 2.0 flow.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Access Token | Your Pinterest OAuth access token | Yes | `-` |
### OAuth 2.0
Authenticate using Pinterest OAuth 2.0 for full API access with token refresh capabilities.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| App ID | Your Pinterest App ID from the developer portal | Yes | `-` |
| App Secret | Your Pinterest App Secret from the developer portal | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://www.pinterest.com/oauth/`
- **Token URL**: `https://api.pinterest.com/v5/oauth/token`
- **Scopes**: `boards:read`, `boards:write`, `pins:read`, `pins:write`, `user_accounts:read`
## Available Actions
### Parameters
Number of boards per page (max 250) (Default: `25`)
Cursor for pagination to get the next page
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"boards": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Boards",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"bookmark": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Bookmark"
}
},
"required": [
"success"
],
"title": "ListBoardsOutput",
"type": "object"
}
```
### Parameters
The ID of the board to get sections from
Number of sections per page (max 250) (Default: `25`)
Cursor for pagination
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"board_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Board Id"
},
"sections": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Sections",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"bookmark": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Bookmark"
}
},
"required": [
"success"
],
"title": "GetBoardSectionsOutput",
"type": "object"
}
```
### Parameters
The ID of the board to pin to
Title of the pin
URL of the image to pin
Description of the pin
Source link/URL for the pin
Alt text for accessibility
ID of the board section
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Link"
},
"board_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Board Id"
},
"board_section_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Board Section Id"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"pin": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Pin"
}
},
"required": [
"success"
],
"title": "CreatePinOutput",
"type": "object"
}
```
### Parameters
The ID of the board to list pins from
ID of the board section (optional)
Number of pins per page (max 250) (Default: `25`)
Cursor for pagination
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"board_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Board Id"
},
"board_section_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Board Section Id"
},
"pins": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Pins",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
},
"bookmark": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Bookmark"
}
},
"required": [
"success"
],
"title": "ListPinsOutput",
"type": "object"
}
```
## Limits & Quotas
- `page_size` is clamped to [1, 250].
- 401 → auth error; 404 → resource-not-found; 400 on create → likely
invalid `media_url` or board id.
## Related integrations
## Links
- [Pinterest](https://www.pinterest.com)
---
# Pipedrive Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/pipedrive
Sales CRM and pipeline management platform for tracking deals, contacts, activities, and leads.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/pipedrive/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Pipedrive** to any ModuleX agent or workflow. Sales CRM and pipeline management platform. Connects to the Pipedrive REST API (`{your-domain}.pipedrive.com/api/v1` and `/api/v2`) to manage deals, contacts, leads, activities, organizations, and notes.
**Categories**: CRM · Sales · **Auth**: OAuth2 · **Actions**: 26
## Authentication
### OAuth2 Authentication
Connect using Pipedrive OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Pipedrive OAuth App Client ID | Yes | `-` |
| Client Secret | Pipedrive OAuth App Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://oauth.pipedrive.com/oauth/authorize`
- **Token URL**: `https://oauth.pipedrive.com/oauth/token`
- **Scopes**: `deals:full`, `contacts:full`, `leads:full`, `activities:full`, `search:read`, `users:read`, `admin`
## Available Actions
### Parameters
Subject of the activity
Type of the activity (e.g. call, meeting, task, deadline, email, lunch). Must match an ActivityType key_string in Pipedrive.
ID of the user whom the activity will be assigned to. If omitted, assigned to the authorized user.
ID of the deal this activity will be associated with
ID of the lead this activity will be associated with
ID of the organization this activity will be associated with
ID of the project this activity will be associated with
Due date of the activity. Format: YYYY-MM-DD
Due time of the activity in UTC. Format: HH:MM
Duration of the activity. Format: HH:MM
Set the activity as Busy or Free
Whether the activity is done or not
Note of the activity (HTML format)
Additional details about the activity that will be synced to your external calendar
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "AddActivityOutput",
"type": "object"
}
```
### Parameters
Deal title
ID of the user who will be marked as the owner of this deal
ID of the person this deal will be associated with
ID of the organization this deal will be associated with
ID of the pipeline this deal will be placed in
ID of the stage this deal will be placed in
Value of the deal. If omitted, value will be set to 0.
Currency of the deal (3-character code). If omitted, uses the default currency of the authorized user.
Status of the deal. Allowed values: open, won, lost, deleted
Deal success probability percentage
Message about why the deal was lost (when status=lost)
Visibility of the deal. 1 = Owner & followers (private), 3 = Entire company (shared)
Expected close date of the deal. Format: YYYY-MM-DD
Content of a note to attach to the deal after creation
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "AddDealOutput",
"type": "object"
}
```
### Parameters
The type of the item. Allowed values: lead, person, deal, organization
The IDs of labels to add. Element type: string
The ID of the lead (required when type=lead)
The ID of the person (required when type=person)
The ID of the deal (required when type=deal)
The ID of the organization (required when type=organization)
Set to true to replace existing labels with the new ones, false to append (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "AddLabelsOutput",
"type": "object"
}
```
### Parameters
The name of the lead
The ID of a person to link to. Required unless organization_id is specified.
The ID of an organization to link to. Required unless person_id is specified.
The ID of the user who will own the lead
The IDs of lead labels to associate. Element type: string (UUID)
Expected close date. Format: YYYY-MM-DD
Visibility of the lead. Allowed values: 1, 3, 5, 7
Whether the lead was seen in the Pipedrive UI
A note to add to the lead
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "AddLeadOutput",
"type": "object"
}
```
### Parameters
The content of the note in HTML format
The ID of the lead to attach the note to
The ID of the deal to attach the note to
The ID of the person to attach the note to
The ID of the organization to attach the note to
The ID of the user marked as the author (admin only)
Pin the note to the deal (requires deal_id) (Default: `false`)
Pin the note to the lead (requires lead_id) (Default: `false`)
Pin the note to the organization (requires organization_id) (Default: `false`)
Pin the note to the person (requires person_id) (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "AddNoteOutput",
"type": "object"
}
```
### Parameters
Organization name
ID of the user who will be marked as the owner
Visibility. 1 = Owner & followers (private), 3 = Entire company (shared)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "AddOrganizationOutput",
"type": "object"
}
```
### Parameters
Person name
ID of the user who will be marked as the owner
ID of the organization this person will belong to
Email addresses. Element type: object with keys {value, primary, label}
Phone numbers. Element type: object with keys {value, primary, label}
Visibility. 1 = Owner & followers (private), 3 = Entire company (shared)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "AddPersonOutput",
"type": "object"
}
```
### Parameters
Maximum number of results to return. If not provided, all leads are returned.
Filter leads by the given user ID
Filter leads by the given person ID
Filter leads by the given organization ID
The ID of the filter to use. Takes precedence over other filters.
Field and direction to sort by. Valid fields: id, title, owner_id, creator_id, was_seen, expected_close_date, next_activity_id, add_time, update_time
### Response
```json
{
"$defs": {
"LeadItem": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"owner_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Owner Id"
},
"person_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Person Id"
},
"organization_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Organization Id"
},
"was_seen": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Was Seen"
},
"expected_close_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Expected Close Date"
},
"add_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Add Time"
},
"update_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Update Time"
}
},
"title": "LeadItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"leads": {
"items": {
"$ref": "#/$defs/LeadItem"
},
"title": "Leads",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetAllLeadsOutput",
"type": "object"
}
```
### Parameters
The ID of the deal to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetDealOutput",
"type": "object"
}
```
### Parameters
The ID of the lead to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetLeadByIdOutput",
"type": "object"
}
```
### Parameters
The ID of the person to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "GetPersonDetailsOutput",
"type": "object"
}
```
### Parameters
The ID of the filter to apply
Filter by owner user ID
Filter by associated person ID
Filter by associated organization ID
Filter by pipeline ID
Filter by stage ID
Filter by status. Allowed values: open, won, lost, deleted
Field to sort by. Allowed values: id, update_time, add_time
Sort direction. Allowed values: asc, desc
Maximum number of entries to return (max 500)
Cursor for pagination to the next page of results
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"deals": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Deals",
"type": "array"
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Cursor"
}
},
"required": [
"success"
],
"title": "ListDealsOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"LabelOption": {
"additionalProperties": false,
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Label"
},
"value": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
}
},
"title": "LabelOption",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"options": {
"items": {
"$ref": "#/$defs/LabelOption"
},
"title": "Options",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListLeadLabelIdsOptionsOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"LabelOption": {
"additionalProperties": false,
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Label"
},
"value": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
}
},
"title": "LabelOption",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"options": {
"items": {
"$ref": "#/$defs/LabelOption"
},
"title": "Options",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListOrganizationLabelIdsOptionsOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"LabelOption": {
"additionalProperties": false,
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Label"
},
"value": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
}
},
"title": "LabelOption",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"options": {
"items": {
"$ref": "#/$defs/LabelOption"
},
"title": "Options",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListPersonLabelIdsOptionsOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"UserOption": {
"additionalProperties": false,
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Label"
},
"value": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
}
},
"title": "UserOption",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"options": {
"items": {
"$ref": "#/$defs/UserOption"
},
"title": "Options",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListUserIdOptionsOutput",
"type": "object"
}
```
### Parameters
The ID of the deal to merge (will be removed)
The ID of the deal to merge into (will be kept)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "MergeDealsOutput",
"type": "object"
}
```
### Parameters
The ID of the person to merge (will be removed)
The ID of the person to merge into (will be kept, data prioritized on conflict)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "MergePersonsOutput",
"type": "object"
}
```
### Parameters
The ID of the lead whose notes to deduplicate
The ID of the deal whose notes to deduplicate
The ID of the person whose notes to deduplicate
The ID of the organization whose notes to deduplicate
The ID of the user whose notes to deduplicate
The ID of the project whose notes to deduplicate
Only remove duplicate notes that contain this keyword
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"total_notes": {
"default": 0,
"title": "Total Notes",
"type": "integer"
},
"duplicates_found": {
"default": 0,
"title": "Duplicates Found",
"type": "integer"
},
"duplicates_removed": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Duplicates Removed",
"type": "array"
}
},
"required": [
"success"
],
"title": "RemoveDuplicateNotesOutput",
"type": "object"
}
```
### Parameters
The type of the item. Allowed values: lead, person, deal, organization
ID of the entity to remove labels from
The label IDs to remove. Element type: string
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "RemoveLabelsOutput",
"type": "object"
}
```
### Parameters
The search term (minimum 2 characters, or 1 with exact_match)
When true, only full exact matches are returned (not case sensitive)
Fields to search from. Allowed values: custom_fields, notes, title. Element type: string
Filter by person ID
Filter by organization ID
Optional fields to include. Allowed: lead.was_seen
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchLeadsOutput",
"type": "object"
}
```
### Parameters
The term to search for in note content
Filter by lead ID
Filter by deal ID
Filter by person ID
Filter by organization ID
Filter by user ID
Sort field. Allowed: id, user_id, deal_id, org_id, person_id, content, add_time, update_time
Sort direction. Allowed: ASC, DESC (Default: `DESC`)
Date from which to fetch notes. Format: YYYY-MM-DD
Date until which to fetch notes. Format: YYYY-MM-DD
Maximum number of results to return
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"notes": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Notes",
"type": "array"
},
"total": {
"default": 0,
"title": "Total",
"type": "integer"
}
},
"required": [
"success"
],
"title": "SearchNotesOutput",
"type": "object"
}
```
### Parameters
The search term (minimum 2 characters, or 1 with exact_match)
Fields to search from. Allowed: custom_fields, email, notes, phone, name. Element type: string
When true, only full exact matches are returned (not case sensitive)
Filter by organization ID (upper limit: 2000)
Optional fields to include. Allowed: person.picture
Pagination start offset
Items per page
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"items": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Items",
"type": "array"
}
},
"required": [
"success"
],
"title": "SearchPersonsOutput",
"type": "object"
}
```
### Parameters
ID of the deal to update
New deal title
ID of the new owner user
ID of the person to associate
ID of the organization to associate
ID of the pipeline
ID of the stage in the pipeline
Value of the deal
Currency (3-character code)
Status. Allowed values: open, won, lost, deleted
Deal success probability percentage
Reason the deal was lost (when status=lost)
Visibility. 1 = private, 3 = shared
A note to add to the deal
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "UpdateDealOutput",
"type": "object"
}
```
### Parameters
The ID of the lead to update
New title of the lead
ID of the person to link to
ID of the organization to link to
ID of the new owner user
Lead label IDs. Element type: string (UUID)
Expected close date. Format: YYYY-MM-DD
Visibility. Allowed values: 1, 3, 5, 7
Whether the lead was seen in the UI
Whether the lead is archived
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "UpdateLeadOutput",
"type": "object"
}
```
### Parameters
The ID of the person to update
New name of the person
ID of the new owner user
ID of the organization this person will belong to
Email addresses. Element type: object with keys {value, primary, label}
Phone numbers. Element type: object with keys {value, primary, label}
Visibility. 1 = private, 3 = shared
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
}
},
"required": [
"success"
],
"title": "UpdatePersonOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limits**: Pipedrive enforces per-plan rate limits. Professional plan: 200 requests/10 seconds; Enterprise plan: 400 requests/10 seconds. Exceeding the limit returns HTTP 429.
- **Pagination**: List endpoints use cursor-based (v2) or offset-based (v1) pagination. The `list_deals` tool supports cursor; `get_all_leads` auto-paginates.
- **Error model**: Non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising. The error string includes the HTTP status code and response body for debugging.
## Related integrations
## Links
- [Pipedrive](https://www.pipedrive.com)
---
# PostgreSQL Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/postgresql
PostgreSQL database integration for executing SQL queries, managing tables, and performing CRUD operations. Uses the asyncpg driver.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/postgresql/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **PostgreSQL** to any ModuleX agent or workflow. PostgreSQL database integration via the `asyncpg` driver. Provides raw SQL execution + CRUD + upsert + introspection.
**Categories**: Databases · Database · Data Management · Storage · **Auth**: PostgreSQL Database Credentials · **Actions**: 10
## Authentication
### PostgreSQL Database Credentials
Authenticate using PostgreSQL connection credentials (host/port/user/password/database).
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Host | PostgreSQL server hostname or IP | Yes | `localhost or postgres.example.com` |
| Port | PostgreSQL server port (defaults to 5432 if omitted) | No | `5432` |
| Username | PostgreSQL username for authentication | Yes | `-` |
| Password | PostgreSQL password for authentication | Yes | `-` |
| Database | The database name to connect to | Yes | `-` |
| SSL Mode | SSL mode: 'disabled', 'verify' (default — full verify), or 'skip_verification' (encrypted but no cert check) | No | `verify | skip_verification | disabled` |
## Available Actions
### Parameters
The SQL to execute
Values for $1, $2, ... placeholders
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"row_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Row Count"
},
"data": {
"anyOf": [
{
"items": {
"additionalProperties": true,
"type": "object"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Data"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"affected_rows": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Affected Rows"
}
},
"required": [
"success"
],
"title": "ExecuteRawQueryOutput",
"type": "object"
}
```
### Parameters
The table name
Column-value pairs to insert
The schema name (default 'public') (Default: `public`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"table": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Table"
},
"schema_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Schema Name"
},
"inserted_row": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Inserted Row"
},
"columns": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Columns"
}
},
"required": [
"success"
],
"title": "CreateRowOutput",
"type": "object"
}
```
### Parameters
The table name
WHERE condition with '?' placeholders
Values matching the '?' placeholders in the condition
The schema name (default 'public') (Default: `public`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"table": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Table"
},
"schema_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Schema Name"
},
"affected_rows": {
"default": 0,
"title": "Affected Rows",
"type": "integer"
},
"deleted_rows": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Deleted Rows",
"type": "array"
}
},
"required": [
"success"
],
"title": "DeleteRowOutput",
"type": "object"
}
```
### Parameters
The table name
Column-value pairs to update
WHERE condition with '?' placeholders
Values matching the '?' placeholders
The schema name (default 'public') (Default: `public`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"table": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Table"
},
"schema_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Schema Name"
},
"affected_rows": {
"default": 0,
"title": "Affected Rows",
"type": "integer"
},
"updated_columns": {
"items": {
"type": "string"
},
"title": "Updated Columns",
"type": "array"
},
"updated_rows": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Updated Rows",
"type": "array"
}
},
"required": [
"success"
],
"title": "UpdateRowOutput",
"type": "object"
}
```
### Parameters
The table name
Column-value pairs to insert/update
Column to use for conflict detection (usually PK)
The schema name (default 'public') (Default: `public`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"table": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Table"
},
"schema_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Schema Name"
},
"upserted_row": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Upserted Row"
},
"conflict_target": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Conflict Target"
}
},
"required": [
"success"
],
"title": "UpsertRowOutput",
"type": "object"
}
```
### Parameters
The table name
The column to filter by
Comparison operator (=, >, >=, <, !=, <=, LIKE, ILIKE) (Default: `=`)
Value to compare against (typed dynamically)
The schema name (default 'public') (Default: `public`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"table": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Table"
},
"schema_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Schema Name"
},
"row_count": {
"default": 0,
"title": "Row Count",
"type": "integer"
},
"data": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Data",
"type": "array"
}
},
"required": [
"success"
],
"title": "FindRowOutput",
"type": "object"
}
```
### Parameters
The table name
WHERE condition with '?' placeholders
Values matching the '?' placeholders in the condition
The schema name (default 'public') (Default: `public`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"table": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Table"
},
"schema_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Schema Name"
},
"row_count": {
"default": 0,
"title": "Row Count",
"type": "integer"
},
"data": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Data",
"type": "array"
}
},
"required": [
"success"
],
"title": "ExecuteQueryWithConditionOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"schemas": {
"items": {
"type": "string"
},
"title": "Schemas",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListSchemasOutput",
"type": "object"
}
```
### Parameters
The schema name (default 'public') (Default: `public`)
### Response
```json
{
"$defs": {
"TableEntry": {
"additionalProperties": false,
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
}
},
"title": "TableEntry",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"schema_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Schema Name"
},
"tables": {
"items": {
"$ref": "#/$defs/TableEntry"
},
"title": "Tables",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListTablesOutput",
"type": "object"
}
```
### Parameters
The table name
The schema name (default 'public') (Default: `public`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"table": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Table"
},
"schema_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Schema Name"
},
"columns": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Columns",
"type": "array"
},
"column_count": {
"default": 0,
"title": "Column Count",
"type": "integer"
},
"primary_keys": {
"items": {
"type": "string"
},
"title": "Primary Keys",
"type": "array"
}
},
"required": [
"success"
],
"title": "DescribeTableOutput",
"type": "object"
}
```
## Limits & Quotas
- 60s connection timeout.
- `find_row` operator allowlist: `=`, `>`, `>=`, `<`, `!=`, `<=`,
`LIKE`, `ILIKE` (case-insensitive accepted as `like`/`ilike` too).
- `asyncpg` is imported lazily so the manifest can be inspected
even without the driver installed.
## Related integrations
## Links
- [PostgreSQL](https://www.postgresql.org/)
---
# PostGrid Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/postgrid
Programmatic direct mail delivery via the PostGrid Print & Mail API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/postgrid/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **PostGrid** to any ModuleX agent or workflow. Programmatic direct mail delivery via the PostGrid Print & Mail API (`api.postgrid.com/print-mail/v1`).
**Categories**: Marketing & Advertising · Marketing · Business Services · **Auth**: API Key · **Actions**: 3
## Authentication
### API Key Authentication
Authenticate using your PostGrid API key
Sign in at https://app.postgrid.com
Navigate to 'Settings' > 'API Keys'
Copy your live or test API key
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| PostGrid API Key | Your PostGrid API key from app.postgrid.com | Yes | `live_sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
The first name of the contact
The last name of the contact
The contact's company name
The contact's first address line
The contact's second address line
The contact's city
The province or state of the contact
The contact's email address
The contact's phone number
The contact's job title
The postal code or ZIP code of the contact
ISO 3166-1 country code of the contact's address. Defaults to CA (Default: `CA`)
A description for the contact
If true, skip address verification and mark the address as failed
### Response
```json
{
"$defs": {
"ContactResource": {
"additionalProperties": false,
"description": "A contact object returned by the PostGrid API.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"object": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Object"
},
"live": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Live"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Name"
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Name"
},
"company_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Company Name"
},
"address_line1": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Address Line1"
},
"address_line2": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Address Line2"
},
"city": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "City"
},
"province_or_state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Province Or State"
},
"postal_or_zip": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Postal Or Zip"
},
"country": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Country"
},
"country_code": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Country Code"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"phone_number": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Phone Number"
},
"job_title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Job Title"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"address_status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Address Status"
}
},
"title": "ContactResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"contact": {
"anyOf": [
{
"$ref": "#/$defs/ContactResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateContactOutput",
"type": "object"
}
```
### Parameters
The ID or contact object of the receiver
The ID or contact object of the sender
The HTML content of the letter
Location where the address will be placed. One of: top_first_page, insert_blank_page
Whether the letter is double sided
Whether the letter will be printed in color
Page number to be perforated
Extra services for the letter. One of: certified, certified_return_receipt, registered
Envelope type. One of: standard_double_window, flat
The ID of the return envelope to be used
Desired date for the letter to be sent out (ISO 8601 format)
A description for the letter
Whether to use express shipping
Mailing class. One of: standard_class, first_class. Defaults to first_class
Letter size. One of: us_letter, us_legal, a4
### Response
```json
{
"$defs": {
"LetterResource": {
"additionalProperties": false,
"description": "A letter object returned by the PostGrid API.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"object": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Object"
},
"live": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Live"
},
"send_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Send Date"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
}
},
"title": "LetterResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"letter": {
"anyOf": [
{
"$ref": "#/$defs/LetterResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateLetterOutput",
"type": "object"
}
```
### Parameters
The ID or contact object of the receiver
The ID or contact object of the sender
The HTML content for the front of the postcard
The HTML content for the back of the postcard
Postcard size. One of: 6x4, 9x6, 11x6
Desired date for the postcard to be sent out (ISO 8601 format)
Whether to use express shipping
A description for the postcard
Mailing class. One of: standard_class, first_class. Defaults to first_class
### Response
```json
{
"$defs": {
"PostcardResource": {
"additionalProperties": false,
"description": "A postcard object returned by the PostGrid API.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"object": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Object"
},
"live": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Live"
},
"send_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Send Date"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"size": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
}
},
"title": "PostcardResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"postcard": {
"anyOf": [
{
"$ref": "#/$defs/PostcardResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreatePostcardOutput",
"type": "object"
}
```
## Limits & Quotas
- No publicly documented rate limits. PostGrid applies per-account request limits based on plan tier.
- Sending physical mail incurs per-item costs based on the PostGrid pricing plan.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [PostGrid](https://www.postgrid.com)
---
# PostHog Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/posthog
Product analytics platform: events, persons, groups, cohorts, dashboards, insights, experiments, feature flags, surveys, session recordings, error tracking, and more (78 actions).
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/posthog/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **PostHog** to any ModuleX agent or workflow. Product analytics platform integration via the PostHog REST + ingest APIs. Pure HTTP. **78 actions** — the largest single integration in the package.
**Categories**: Analytics & Data · Data & Analytics · Data · Development · **Auth**: PostHog API Key · **Actions**: 78
## Authentication
### PostHog API Key Authentication
Connect to PostHog using your personal API key, project ID, and instance URL.
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Personal API Key | Your PostHog personal API key | Yes | `phx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
| Project ID | PostHog project ID (found in project settings) | Yes | `12345` |
| Instance URL | Your PostHog instance URL — required. MUST be ONLY the host with scheme, no trailing slash, no path. Pick the line that matches your workspace:
• US cloud: https://us.posthog.com
• EU cloud: https://eu.posthog.com
• Self-hosted: https://posthog.your-company.com
DO NOT append /api, /api/projects, or any other path — the rest of the URL is added automatically. Trailing slash also not allowed. | Yes | `https://us.posthog.com` |
## Available Actions
### Parameters
PostHog project ID
PostHog instance URL (default: https://app.posthog.com)
Max results (Default: `100`)
Results to skip (Default: `0`)
Search query
Filter by pinned status
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
dashboard_id to retrieve
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Dashboard name
PostHog instance URL (default: https://app.posthog.com)
Dashboard description
Pin the dashboard
Tag list
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Dashboard ID
PostHog instance URL (default: https://app.posthog.com)
New name
New description
Pin status
Tag list
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
dashboard_id to delete
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
experiment_id to retrieve
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Experiment name
Feature flag key linked to the experiment
PostHog instance URL (default: https://app.posthog.com)
Experiment description
'product' or 'web' (Default: `product`)
Primary metric definitions
Secondary metric definitions
Experiment variants
Minimum detectable effect % (Default: `30`)
Filter out internal/test accounts (Default: `true`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Experiment ID
PostHog instance URL (default: https://app.posthog.com)
New name
New description
Primary metrics
Secondary metrics
Launch the experiment
'won' / 'lost' / 'inconclusive'
Archive the experiment
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
experiment_id to delete
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Experiment ID
PostHog instance URL (default: https://app.posthog.com)
Force refresh (Default: `false`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Feature flag ID (integer). Mutually exclusive with flag_key — provide one or the other.
Feature flag key (string). Mutually exclusive with flag_id — provide one or the other.
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Flag key
Flag name
PostHog instance URL (default: https://app.posthog.com)
Description
Flag filters
Active (Default: `true`)
Tag list
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Flag key to update
PostHog instance URL (default: https://app.posthog.com)
New name
New description
Updated filters
Active state
Tag list
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
flag_id to delete
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
PostHog instance URL (default: https://app.posthog.com)
Max results (Default: `100`)
Results to skip (Default: `0`)
Search query
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
insight_id to retrieve
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Insight name
PostHog instance URL (default: https://app.posthog.com)
Description
Insight filter config
HogQL/JSON query
Dashboard IDs to attach
Tag list
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Insight ID
PostHog instance URL (default: https://app.posthog.com)
New name
New description
Filter config
Query
Tag list
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
insight_id to delete
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Query body
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
PostHog instance URL (default: https://app.posthog.com)
Max results (Default: `100`)
Results to skip (Default: `0`)
Search query
Filter by status
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
issue_id to retrieve
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
PostHog instance URL (default: https://app.posthog.com)
Max results (Default: `100`)
Results to skip (Default: `0`)
Search query
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
survey_id to retrieve
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Survey name
'popover' / 'widget' / 'api' (Default: `popover`)
PostHog instance URL (default: https://app.posthog.com)
Description
Survey questions
Trigger conditions
Linked feature flag ID
Targeting filters
Survey appearance config
Start date
End date
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Survey ID
PostHog instance URL (default: https://app.posthog.com)
New name
New description
Questions
Trigger conditions
Archive the survey
Start date
End date
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
survey_id to delete
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
Organization ID
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
PostHog instance URL (default: https://app.posthog.com)
Max results (Default: `100`)
Results to skip (Default: `0`)
Search query
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
PostHog instance URL (default: https://app.posthog.com)
Max results (Default: `100`)
Results to skip (Default: `0`)
Search query
Filter by event names
Filter by property type
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project API key
Distinct user ID
Event name
Event properties
ISO 8601 timestamp
PostHog ingest URL (default: https://us.i.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project API key
List of event objects
Flag historical imports (Default: `false`)
PostHog ingest URL (default: https://us.i.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project API key
Distinct user ID
Properties to set
PostHog ingest URL (default: https://us.i.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project API key
Canonical distinct ID
Alias distinct ID to merge in
PostHog ingest URL (default: https://us.i.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project API key
Distinct user ID
Group memberships
Person properties
Group properties
PostHog ingest URL (default: https://us.i.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project API key
Group type (e.g. 'company')
Group key (the unique ID)
Properties to set on the group
PostHog ingest URL (default: https://us.i.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
PostHog instance URL (default: https://app.posthog.com)
Max results (Default: `100`)
Results to skip (Default: `0`)
Search query
Filter by distinct ID
Filter by email
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
person_id to retrieve
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Person ID
Properties to set
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Person ID
Also delete events (GDPR) (Default: `false`)
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Person IDs to delete
Also delete events (Default: `false`)
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Group type index (0-4)
PostHog instance URL (default: https://app.posthog.com)
Search query
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Group type index
Group key
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
cohort_id to retrieve
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Cohort name
PostHog instance URL (default: https://app.posthog.com)
Description
Static cohort (Default: `false`)
Filter config
Group filters
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Cohort ID
PostHog instance URL (default: https://app.posthog.com)
New name
New description
Filters
Groups
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
cohort_id to delete
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Cohort ID
PostHog instance URL (default: https://app.posthog.com)
Max results (Default: `100`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
PostHog instance URL (default: https://app.posthog.com)
Max results (Default: `100`)
Results to skip (Default: `0`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
recording_id to retrieve
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
recording_id to delete
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
PostHog instance URL (default: https://app.posthog.com)
Max results (Default: `100`)
Results to skip (Default: `0`)
Search query
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
action_id to retrieve
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Action name
PostHog instance URL (default: https://app.posthog.com)
Description
Action steps (conditions)
Tag list
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Action ID
PostHog instance URL (default: https://app.posthog.com)
New name
New description
Steps
Tag list
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Action ID
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Action name to find + delete
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
PostHog instance URL (default: https://app.posthog.com)
Max results (Default: `100`)
Results to skip (Default: `0`)
Search query
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
annotation_id to retrieve
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Annotation text
Date marker (ISO 8601)
PostHog instance URL (default: https://app.posthog.com)
Linked insight (dashboard item)
'dashboard_item' / 'project' / 'organization' (Default: `organization`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Annotation ID
PostHog instance URL (default: https://app.posthog.com)
New content
New date marker
New scope
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
annotation_id to delete
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
PostHog instance URL (default: https://app.posthog.com)
Max results (Default: `100`)
Results to skip (Default: `0`)
Filter by insight ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
alert_id to retrieve
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Insight ID
Alert name
PostHog instance URL (default: https://app.posthog.com)
Threshold config
User IDs to notify
Enabled (Default: `true`)
Notification target config
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Alert ID
PostHog instance URL (default: https://app.posthog.com)
New name
Threshold config
User IDs
Enabled state
Notification targets
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
alert_id to delete
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
PostHog instance URL (default: https://app.posthog.com)
Max results (Default: `100`)
Results to skip (Default: `0`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
feature_id to retrieve
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Feature name
PostHog instance URL (default: https://app.posthog.com)
Description
draft / beta / general-availability / archived (Default: `beta`)
Documentation URL
Linked feature flag ID
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Feature ID
PostHog instance URL (default: https://app.posthog.com)
New name
New description
Updated stage
Updated documentation URL
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
feature_id to delete
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
### Parameters
PostHog project ID
Feature name to find + delete
PostHog instance URL (default: https://app.posthog.com)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"result": {
"default": null,
"title": "Result"
}
},
"required": [
"success"
],
"title": "PostHogResult",
"type": "object"
}
```
## Related integrations
## Links
- [PostHog](https://posthog.com)
---
# Postman Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/postman
API development and testing platform for building, monitoring, and managing APIs
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/postman/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Postman** to any ModuleX agent or workflow. API development and testing platform for building, monitoring, and managing APIs against the Postman REST API (`api.getpostman.com`).
**Categories**: Developer Tools & Infrastructure · Api Testing · **Auth**: API Key · **Actions**: 4
## Authentication
### API Key Authentication
Authenticate using your Postman API key
Go to https://web.postman.co and sign in
Click your avatar in the top-right, then select Settings
Navigate to the 'API Keys' tab
Generate a new API key or copy your existing one
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Postman API Key | Your Postman API key from web.postman.co/settings/me/api-keys | Yes | `PMAK-xxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
The name for the new environment
The ID of the workspace to create the environment in
List of variable objects with keys: key (string), value (string), enabled (boolean), type ('secret' or 'default')
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"environment_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Environment Id"
},
"environment_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Environment Name"
}
},
"required": [
"success"
],
"title": "CreateEnvironmentOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"WorkspaceSummary": {
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Type"
}
},
"title": "WorkspaceSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"workspaces": {
"items": {
"$ref": "#/$defs/WorkspaceSummary"
},
"title": "Workspaces",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListWorkspaceIdOptionsOutput",
"type": "object"
}
```
### Parameters
The ID of the monitor to run
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"run": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Run"
}
},
"required": [
"success"
],
"title": "RunMonitorOutput",
"type": "object"
}
```
### Parameters
The ID of the environment containing the variable
The variable key (name) to update
The new value for the variable
The ID of the workspace containing the environment
Whether the variable is enabled or not
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"environment_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Environment Id"
},
"environment_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Environment Name"
}
},
"required": [
"success"
],
"title": "UpdateVariableOutput",
"type": "object"
}
```
## Limits & Quotas
- **Free plan**: 25 requests/minute per API key.
- **Paid plans**: Higher limits; see
https://learning.postman.com/docs/developer/postman-api/postman-api-rate-limits/.
- **Error model**: non-2xx responses and timeouts are caught and returned as
`success=False` + `error` rather than raising. Plan for retries on the agent
side based on the error string.
## Related integrations
## Links
- [Postman](https://www.postman.com)
---
# Product Hunt Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/product-hunt
Discover and explore tech products, topics, and community posts via the Product Hunt GraphQL API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/product_hunt/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Product Hunt** to any ModuleX agent or workflow. Discover and explore tech products, topics, and community posts via the Product Hunt GraphQL API (`api.producthunt.com/v2/api/graphql`).
**Categories**: Social Media · Productivity & Collaboration · Marketing · **Auth**: OAuth2 · **Actions**: 1
## Authentication
### OAuth2 Authentication
Connect using Product Hunt OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Product Hunt OAuth App Client ID | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
| Client Secret | Product Hunt OAuth App Client Secret | Yes | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
#### OAuth Configuration
- **Authorization URL**: `https://api.producthunt.com/v2/oauth/authorize`
- **Token URL**: `https://api.producthunt.com/v2/oauth/token`
- **Scopes**: `public`, `private`
## Available Actions
### Response
```json
{
"$defs": {
"TopicOption": {
"additionalProperties": false,
"description": "A single topic option with slug and display name.",
"properties": {
"value": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
},
"label": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Label"
}
},
"title": "TopicOption",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"topics": {
"items": {
"$ref": "#/$defs/TopicOption"
},
"title": "Topics",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListTopicOptionsOutput",
"type": "object"
}
```
## Limits & Quotas
- Product Hunt API v2 rate limits are not publicly documented in detail; typical observed limit is approximately 450 requests per 15-minute window per token.
- No per-request pricing; API access is free for authorized applications.
- Error model: non-2xx responses and GraphQL-level errors are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Product Hunt](https://www.producthunt.com)
---
# Pulse Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/pulse
Extract text and structured content from PDFs, images, and Office files using Pulse OCR. Returns clean markdown, page counts, layout bounding boxes, chunks, and extracted figures.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/pulse/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Pulse** to any ModuleX agent or workflow. Extract text and structured content from PDFs, images, and Office files using Pulse OCR, against the Pulse REST API (`api.runpulse.com`).
**Categories**: AI & Machine Learning · Document Processing · Ocr · **Auth**: API Key · **Actions**: 1
## Authentication
### API Key Authentication
Authenticate using your Pulse API key
Go to https://www.runpulse.com and sign up or log in
Open your dashboard and navigate to the API keys section
Create a new API key or copy your existing one
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Pulse API Key | Your Pulse API key from the runpulse.com dashboard | Yes | `-` |
## Available Actions
### Parameters
Public HTTP(S) URL to a document to process (PDF, image, or Office file)
Page range to process, 1-indexed (e.g. "1-2,5"). Omit for all pages.
Chunking strategies (comma-separated: semantic, header, page, recursive)
Maximum characters per chunk when chunking is enabled
Whether to include HTML in the response
Whether to extract figures from the document
Whether to generate descriptions/captions for extracted figures
### Response
```json
{
"$defs": {
"PlanInfo": {
"additionalProperties": false,
"description": "Plan usage information returned with each extraction.",
"properties": {
"pages_used": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Pages Used"
},
"tier": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Tier"
},
"note": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Note"
}
},
"title": "PlanInfo",
"type": "object"
}
},
"additionalProperties": false,
"description": "Result of parsing a document with Pulse OCR.",
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"markdown": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Markdown"
},
"page_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Page Count"
},
"job_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Job Id"
},
"plan_info": {
"anyOf": [
{
"$ref": "#/$defs/PlanInfo"
},
{
"type": "null"
}
],
"default": null
},
"bounding_boxes": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Bounding Boxes"
},
"extraction_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Extraction Url"
},
"html": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Html"
},
"structured_output": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Structured Output"
},
"chunks": {
"items": {},
"title": "Chunks",
"type": "array"
},
"figures": {
"items": {},
"title": "Figures",
"type": "array"
}
},
"required": [
"success"
],
"title": "ParserOutput",
"type": "object"
}
```
## Limits & Quotas
- **Billing**: Pulse bills in credits; each extraction is billed by
the number of pages (or tables) processed. API keys can carry
per-key credit caps.
- **Large documents**: documents above ~70 pages return an
`extraction_url` pointing at the full results instead of inlining
the markdown.
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising. Plan for
retries on the agent side based on the error string.
## Related integrations
## Links
- [Pulse](https://www.runpulse.com)
---
# Quiver Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/quiver
Generate SVG images from text prompts or vectorize raster images into SVGs using QuiverAI. Supports reference images, style instructions, and multiple output generation.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/quiver/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Quiver** to any ModuleX agent or workflow. AI-powered SVG generation and raster vectorization against the QuiverAI REST API (`api.quiver.ai/v1`). Generate clean, scalable vector graphics from text prompts or convert raster images into editable SVGs.
**Categories**: AI & Machine Learning · Image Generation · Design · **Auth**: API Key · **Actions**: 3
## Authentication
### API Key Authentication
Authenticate using your QuiverAI API key
Go to https://quiver.ai and sign up or log in
Open your account dashboard and navigate to API keys
Create a new API key or copy your existing one
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| QuiverAI API Key | Your QuiverAI API key from quiver.ai | Yes | `-` |
## Available Actions
### Parameters
A text description of the desired SVG
The model to use for SVG generation (e.g. "arrow-1.1") (Default: `arrow-1.1`)
Style or formatting guidance for the SVG output
Reference image URLs to guide SVG generation (up to 4 for arrow-1.1, 16 for arrow-1.1-max)
Number of SVGs to generate (1-16, default 1)
Sampling temperature (0-2, default 1)
Nucleus sampling probability (0-1, default 1)
Maximum output tokens (1-65536)
Token penalty for prior output (-2 to 2, default 0)
### Response
```json
{
"$defs": {
"SvgArtifact": {
"additionalProperties": false,
"description": "A single generated SVG returned in the response ``data`` array.",
"properties": {
"svg": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Svg"
},
"mime_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mime Type"
}
},
"title": "SvgArtifact",
"type": "object"
},
"UsageInfo": {
"additionalProperties": false,
"description": "Token usage statistics returned alongside an SVG response.\n\nQuiver retains these fields for compatibility; they may be zeroed.\nBilling is reported via ``credits`` on the parent output.",
"properties": {
"input_tokens": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Input Tokens"
},
"output_tokens": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Output Tokens"
},
"total_tokens": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Tokens"
}
},
"title": "UsageInfo",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"created": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"svg_content": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Svg Content"
},
"artifacts": {
"items": {
"$ref": "#/$defs/SvgArtifact"
},
"title": "Artifacts",
"type": "array"
},
"credits": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Credits"
},
"usage": {
"anyOf": [
{
"$ref": "#/$defs/UsageInfo"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "TextToSvgOutput",
"type": "object"
}
```
### Parameters
URL of the raster image to vectorize into SVG
The model to use for vectorization (e.g. "arrow-1.1") (Default: `arrow-1.1`)
Automatically crop the image to its dominant subject
Square resize target in pixels (128-4096)
Sampling temperature (0-2, default 1)
Nucleus sampling probability (0-1, default 1)
Maximum output tokens (1-65536)
Token penalty for prior output (-2 to 2, default 0)
### Response
```json
{
"$defs": {
"SvgArtifact": {
"additionalProperties": false,
"description": "A single generated SVG returned in the response ``data`` array.",
"properties": {
"svg": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Svg"
},
"mime_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Mime Type"
}
},
"title": "SvgArtifact",
"type": "object"
},
"UsageInfo": {
"additionalProperties": false,
"description": "Token usage statistics returned alongside an SVG response.\n\nQuiver retains these fields for compatibility; they may be zeroed.\nBilling is reported via ``credits`` on the parent output.",
"properties": {
"input_tokens": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Input Tokens"
},
"output_tokens": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Output Tokens"
},
"total_tokens": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Tokens"
}
},
"title": "UsageInfo",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"created": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"svg_content": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Svg Content"
},
"artifacts": {
"items": {
"$ref": "#/$defs/SvgArtifact"
},
"title": "Artifacts",
"type": "array"
},
"credits": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Credits"
},
"usage": {
"anyOf": [
{
"$ref": "#/$defs/UsageInfo"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "ImageToSvgOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"ModelInfo": {
"additionalProperties": false,
"description": "A single available model row in ``list_models``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"created": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Created"
},
"owned_by": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Owned By"
},
"input_modalities": {
"items": {
"type": "string"
},
"title": "Input Modalities",
"type": "array"
},
"output_modalities": {
"items": {
"type": "string"
},
"title": "Output Modalities",
"type": "array"
},
"context_length": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Context Length"
},
"max_output_length": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Max Output Length"
},
"supported_operations": {
"items": {
"type": "string"
},
"title": "Supported Operations",
"type": "array"
},
"supported_sampling_parameters": {
"items": {
"type": "string"
},
"title": "Supported Sampling Parameters",
"type": "array"
}
},
"title": "ModelInfo",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"models": {
"items": {
"$ref": "#/$defs/ModelInfo"
},
"title": "Models",
"type": "array"
},
"total_models": {
"default": 0,
"title": "Total Models",
"type": "integer"
},
"raw": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Raw"
}
},
"required": [
"success"
],
"title": "ListModelsOutput",
"type": "object"
}
```
## Limits & Quotas
- **Models**: `arrow-1.1` is the default; `arrow-1.1-max` offers higher
fidelity for detailed images and supports more reference images.
- **Generation**: `n` of 1-16 outputs per request; `temperature` 0-2,
`top_p` 0-1, `presence_penalty` -2 to 2, `max_output_tokens` up to
65536.
- **Vectorization**: decoded images cannot exceed 4096 x 4096 px;
`target_size` accepts 128-4096 px.
- **Billing**: each request reports a `credits` debit; `usage` token
fields are retained for compatibility and may be zeroed.
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising. Plan for
retries on the agent side based on the error string.
## Related integrations
## Links
- [Quiver](https://quiver.ai)
---
# Railway Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/railway
Integrate Railway into workflows to list projects, manage services and environments, monitor deployments, trigger and roll back service deployments, and manage environment variables.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/railway/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Railway** to any ModuleX agent or workflow. Manage Railway projects, services, environments, deployments, and environment variables against Railway's public GraphQL API (`backboard.railway.com/graphql/v2`).
**Categories**: Developer Tools & Infrastructure · Cloud · Ci Cd · **Auth**: API Token · **Actions**: 20
## Authentication
### API Token Authentication
Authenticate using your Railway API token
Sign in at https://railway.com and open your account settings
Go to the 'Tokens' section under Account Settings
Create a new token (account, workspace, or project scope)
Paste the token below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Railway API Token | Your Railway API token from account settings | Yes | `-` |
## Available Actions
### Parameters
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
Workspace ID to list projects from
Maximum number of projects to return
Cursor for pagination
### Response
```json
{
"$defs": {
"PageInfo": {
"additionalProperties": false,
"description": "Cursor-pagination metadata returned by list actions.",
"properties": {
"has_next_page": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has Next Page"
},
"end_cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "End Cursor"
}
},
"title": "PageInfo",
"type": "object"
},
"ProjectSummary": {
"additionalProperties": false,
"description": "A single project row in ``list_projects``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"title": "ProjectSummary",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"projects": {
"items": {
"$ref": "#/$defs/ProjectSummary"
},
"title": "Projects",
"type": "array"
},
"page_info": {
"anyOf": [
{
"$ref": "#/$defs/PageInfo"
},
{
"type": "null"
}
],
"default": null
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListProjectsOutput",
"type": "object"
}
```
### Parameters
Railway project ID
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
### Response
```json
{
"$defs": {
"ProjectDetail": {
"additionalProperties": false,
"description": "A project with its services and environments (``get_project``).",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
},
"services": {
"items": {
"$ref": "#/$defs/ProjectService"
},
"title": "Services",
"type": "array"
},
"environments": {
"items": {
"$ref": "#/$defs/ProjectEnvironment"
},
"title": "Environments",
"type": "array"
}
},
"title": "ProjectDetail",
"type": "object"
},
"ProjectEnvironment": {
"additionalProperties": false,
"description": "An environment attached to a project in ``get_project``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
}
},
"title": "ProjectEnvironment",
"type": "object"
},
"ProjectService": {
"additionalProperties": false,
"description": "A service attached to a project in ``get_project``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"icon": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Icon"
}
},
"title": "ProjectService",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"project": {
"anyOf": [
{
"$ref": "#/$defs/ProjectDetail"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetProjectOutput",
"type": "object"
}
```
### Parameters
Project name
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
Project description
Workspace ID to create the project in
Whether the project should be publicly visible
Name for the default environment
Whether to enable pull request deploys
### Response
```json
{
"$defs": {
"CreatedResource": {
"additionalProperties": false,
"description": "A freshly created resource carrying just id + name.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
}
},
"title": "CreatedResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"project": {
"anyOf": [
{
"$ref": "#/$defs/CreatedResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateProjectOutput",
"type": "object"
}
```
### Parameters
Railway project ID
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
Updated project name
Updated project description
Whether the project should be publicly visible
Whether to enable pull request deploy environments
### Response
```json
{
"$defs": {
"UpdatedProject": {
"additionalProperties": false,
"description": "The project echoed back by ``update_project``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
}
},
"title": "UpdatedProject",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"project": {
"anyOf": [
{
"$ref": "#/$defs/UpdatedProject"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "UpdateProjectOutput",
"type": "object"
}
```
### Parameters
Railway project ID
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"deleted": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted"
}
},
"required": [
"success"
],
"title": "DeleteProjectOutput",
"type": "object"
}
```
### Parameters
Railway project ID
Destination workspace ID
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"transferred": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Transferred"
}
},
"required": [
"success"
],
"title": "TransferProjectOutput",
"type": "object"
}
```
### Parameters
Railway project ID
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
### Response
```json
{
"$defs": {
"ProjectMember": {
"additionalProperties": false,
"description": "A single member row in ``list_project_members``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"role": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Role"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"avatar": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Avatar"
}
},
"title": "ProjectMember",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"members": {
"items": {
"$ref": "#/$defs/ProjectMember"
},
"title": "Members",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListProjectMembersOutput",
"type": "object"
}
```
### Parameters
Railway project ID
Environment name
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
Environment ID to clone from
Whether the environment is ephemeral
Whether to skip initial deploys for the environment
Whether to stage initial changes instead of applying them immediately
### Response
```json
{
"$defs": {
"CreatedResource": {
"additionalProperties": false,
"description": "A freshly created resource carrying just id + name.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
}
},
"title": "CreatedResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"environment": {
"anyOf": [
{
"$ref": "#/$defs/CreatedResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateEnvironmentOutput",
"type": "object"
}
```
### Parameters
Railway environment ID
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"deleted": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted"
}
},
"required": [
"success"
],
"title": "DeleteEnvironmentOutput",
"type": "object"
}
```
### Parameters
Railway project ID
Service name
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
GitHub repository in owner/name format to deploy from
Docker image to deploy, for example redis:7-alpine
Git branch to deploy when using a repository source
### Response
```json
{
"$defs": {
"CreatedResource": {
"additionalProperties": false,
"description": "A freshly created resource carrying just id + name.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
}
},
"title": "CreatedResource",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"service": {
"anyOf": [
{
"$ref": "#/$defs/CreatedResource"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreateServiceOutput",
"type": "object"
}
```
### Parameters
Railway service ID
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"deleted": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted"
}
},
"required": [
"success"
],
"title": "DeleteServiceOutput",
"type": "object"
}
```
### Parameters
Railway project ID
Railway service ID
Railway environment ID
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
Maximum number of deployments to return
Cursor for pagination
### Response
```json
{
"$defs": {
"DeploymentSummary": {
"additionalProperties": false,
"description": "A single deployment row in ``list_deployments``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"static_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Static Url"
},
"can_rollback": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Rollback"
},
"can_redeploy": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Redeploy"
}
},
"title": "DeploymentSummary",
"type": "object"
},
"PageInfo": {
"additionalProperties": false,
"description": "Cursor-pagination metadata returned by list actions.",
"properties": {
"has_next_page": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has Next Page"
},
"end_cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "End Cursor"
}
},
"title": "PageInfo",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"deployments": {
"items": {
"$ref": "#/$defs/DeploymentSummary"
},
"title": "Deployments",
"type": "array"
},
"page_info": {
"anyOf": [
{
"$ref": "#/$defs/PageInfo"
},
{
"type": "null"
}
],
"default": null
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListDeploymentsOutput",
"type": "object"
}
```
### Parameters
Railway deployment ID
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
### Response
```json
{
"$defs": {
"DeploymentDetail": {
"additionalProperties": false,
"description": "The deployment detail returned by ``get_deployment``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"static_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Static Url"
},
"can_rollback": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Rollback"
},
"can_redeploy": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Can Redeploy"
}
},
"title": "DeploymentDetail",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"deployment": {
"anyOf": [
{
"$ref": "#/$defs/DeploymentDetail"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetDeploymentOutput",
"type": "object"
}
```
### Parameters
Railway service ID
Railway environment ID
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
Specific Git commit SHA to deploy
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"deployment_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Deployment Id"
}
},
"required": [
"success"
],
"title": "DeployServiceOutput",
"type": "object"
}
```
### Parameters
Railway deployment ID
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"restarted": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Restarted"
}
},
"required": [
"success"
],
"title": "RestartDeploymentOutput",
"type": "object"
}
```
### Parameters
Railway deployment ID to roll back to (must have canRollback)
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"rolled_back": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Rolled Back"
}
},
"required": [
"success"
],
"title": "RollbackDeploymentOutput",
"type": "object"
}
```
### Parameters
Railway deployment ID
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
Maximum number of log lines to return
### Response
```json
{
"$defs": {
"DeploymentLog": {
"additionalProperties": false,
"description": "A single log entry in ``get_deployment_logs``.",
"properties": {
"timestamp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Timestamp"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Message"
},
"severity": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Severity"
}
},
"title": "DeploymentLog",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"logs": {
"items": {
"$ref": "#/$defs/DeploymentLog"
},
"title": "Logs",
"type": "array"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "GetDeploymentLogsOutput",
"type": "object"
}
```
### Parameters
Railway project ID
Railway environment ID
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
Railway service ID. Omit for shared environment variables.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"variables": {
"additionalProperties": true,
"title": "Variables",
"type": "object"
},
"count": {
"default": 0,
"title": "Count",
"type": "integer"
}
},
"required": [
"success"
],
"title": "ListVariablesOutput",
"type": "object"
}
```
### Parameters
Railway project ID
Railway environment ID
Variable name
Variable value
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
Railway service ID. Omit to create or update a shared variable.
Whether to skip automatic redeploys after changing the variable
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"upserted": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Upserted"
}
},
"required": [
"success"
],
"title": "UpsertVariableOutput",
"type": "object"
}
```
### Parameters
Railway project ID
Railway environment ID
Variable name to delete
Railway token type. Use "account" for account, workspace, or OAuth tokens, or "project" for project tokens. (Default: `account`)
Railway service ID. Omit to delete a shared variable.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"deleted": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted"
}
},
"required": [
"success"
],
"title": "DeleteVariableOutput",
"type": "object"
}
```
## Limits & Quotas
- **Transport**: every action is a single POST to the GraphQL endpoint
`https://backboard.railway.com/graphql/v2`.
- **Rate limits**: Railway applies request-rate and complexity limits to
the public API; see the official API docs for current values.
- **Error model**: the GraphQL endpoint answers HTTP 200 even for
logical errors, returning them in a top-level `errors` array. These,
along with non-2xx responses and timeouts, are caught and returned as
`success=False` + `error` rather than raising. Plan for retries on the
agent side based on the error string.
## Related integrations
## Links
- [Railway](https://railway.com)
---
# Reflect Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/reflect
Note-taking and knowledge management via the Reflect API
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/reflect/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Reflect** to any ModuleX agent or workflow. Note-taking and knowledge management via the Reflect API (`reflect.app/api`).
**Categories**: Productivity & Collaboration · Note Taking · Knowledge Management · **Auth**: OAuth2 · **Actions**: 5
## Authentication
### OAuth2 Authentication
Connect using Reflect OAuth (recommended)
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Client ID | Reflect OAuth App Client ID | Yes | `-` |
| Client Secret | Reflect OAuth App Client Secret | Yes | `-` |
#### OAuth Configuration
- **Authorization URL**: `https://reflect.app/oauth`
- **Token URL**: `https://reflect.app/api/oauth/token`
- **Scopes**: `read:graph`, `write:graph`
## Available Actions
### Parameters
The graph identifier
Text to append to the daily note
Name of the list to append to
Date of the daily note in ISO 8601 format. Defaults to today.
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
}
},
"required": [
"success"
],
"title": "AppendDailyNoteOutput",
"type": "object"
}
```
### Parameters
The graph identifier
The URL of the link to create
The link title
The link description
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
}
},
"required": [
"success"
],
"title": "CreateLinkOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"uid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Uid"
},
"graph_ids": {
"items": {
"type": "string"
},
"title": "Graph Ids",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetUserOutput",
"type": "object"
}
```
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"graph_ids": {
"items": {
"type": "string"
},
"title": "Graph Ids",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListGraphIdOptionsOutput",
"type": "object"
}
```
### Parameters
The graph identifier
### Response
```json
{
"$defs": {
"LinkItem": {
"additionalProperties": false,
"description": "A link object returned by the Reflect API.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Title"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"updated_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated At"
}
},
"title": "LinkItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"links": {
"items": {
"$ref": "#/$defs/LinkItem"
},
"title": "Links",
"type": "array"
}
},
"required": [
"success"
],
"title": "ListLinksOutput",
"type": "object"
}
```
## Limits & Quotas
- No documented rate limits from the Reflect API.
- Error model: non-2xx responses and timeouts are caught and returned as `success=False` + `error` rather than raising.
## Related integrations
## Links
- [Reflect](https://reflect.app)
---
# Resend Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/resend
Send transactional and marketing emails, retrieve email status, manage contacts, and view domains with Resend.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/resend/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **Resend** to any ModuleX agent or workflow. Send transactional and marketing emails, retrieve email status, manage contacts, and view domains via the Resend REST API (`api.resend.com`).
**Categories**: Communication · Email · Email Marketing · **Auth**: API Key · **Actions**: 8
## Authentication
### API Key Authentication
Authenticate using your Resend API key
Go to https://resend.com and sign up or log in
Navigate to the 'API Keys' section in the dashboard
Create a new API key (it starts with 're_')
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| Resend API Key | Your Resend API key from resend.com/api-keys | Yes | `re_xxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
Email address to send from (e.g. "sender@example.com" or "Sender Name <sender@example.com>")
Recipient email address (e.g. "recipient@example.com" or "Recipient Name <recipient@example.com>")
Email subject line
Email body content (plain text or HTML based on content_type)
Content type for the body: "text" for plain text or "html" (Default: `text`)
Carbon copy recipient email address
Blind carbon copy recipient email address
Reply-to email address
Schedule email to be sent later in ISO 8601 format
Comma-separated key:value pairs for email tags (e.g. "category:welcome,type:onboarding")
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"to": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "To"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"body": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Body"
}
},
"required": [
"success"
],
"title": "SendOutput",
"type": "object"
}
```
### Parameters
The ID of the email to retrieve
### Response
```json
{
"$defs": {
"EmailTag": {
"additionalProperties": false,
"description": "A single tag name/value pair attached to an email.",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"value": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Value"
}
},
"title": "EmailTag",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"sender": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Sender"
},
"to": {
"items": {
"type": "string"
},
"title": "To",
"type": "array"
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Subject"
},
"html": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Html"
},
"text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Text"
},
"cc": {
"items": {
"type": "string"
},
"title": "Cc",
"type": "array"
},
"bcc": {
"items": {
"type": "string"
},
"title": "Bcc",
"type": "array"
},
"reply_to": {
"items": {
"type": "string"
},
"title": "Reply To",
"type": "array"
},
"last_event": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Event"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"scheduled_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Scheduled At"
},
"tags": {
"items": {
"$ref": "#/$defs/EmailTag"
},
"title": "Tags",
"type": "array"
}
},
"required": [
"success"
],
"title": "GetEmailOutput",
"type": "object"
}
```
### Parameters
Email address of the contact
First name of the contact
Last name of the contact
Whether the contact is unsubscribed from all broadcasts
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
}
},
"required": [
"success"
],
"title": "CreateContactOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"ContactItem": {
"additionalProperties": false,
"description": "A single contact row in ``list_contacts``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Name"
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Name"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"unsubscribed": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Unsubscribed"
}
},
"title": "ContactItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"contacts": {
"items": {
"$ref": "#/$defs/ContactItem"
},
"title": "Contacts",
"type": "array"
},
"has_more": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has More"
}
},
"required": [
"success"
],
"title": "ListContactsOutput",
"type": "object"
}
```
### Parameters
The contact ID or email address to retrieve
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Email"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Name"
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Name"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
},
"unsubscribed": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Unsubscribed"
}
},
"required": [
"success"
],
"title": "GetContactOutput",
"type": "object"
}
```
### Parameters
The contact ID or email address to update
Updated first name
Updated last name
Whether the contact should be unsubscribed from all broadcasts
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
}
},
"required": [
"success"
],
"title": "UpdateContactOutput",
"type": "object"
}
```
### Parameters
The contact ID or email address to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"deleted": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted"
}
},
"required": [
"success"
],
"title": "DeleteContactOutput",
"type": "object"
}
```
### Response
```json
{
"$defs": {
"DomainItem": {
"additionalProperties": false,
"description": "A single domain row in ``list_domains``.",
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Id"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Name"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Status"
},
"region": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Region"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Created At"
}
},
"title": "DomainItem",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"domains": {
"items": {
"$ref": "#/$defs/DomainItem"
},
"title": "Domains",
"type": "array"
},
"has_more": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Has More"
}
},
"required": [
"success"
],
"title": "ListDomainsOutput",
"type": "object"
}
```
## Limits & Quotas
- **Rate limit**: 2 requests/second by default (Resend account level).
- **Scheduling**: emails can be scheduled up to 30 days ahead via
`scheduled_at` (ISO 8601 timestamp).
- **Error model**: non-2xx responses and timeouts are caught and
returned as `success=False` + `error` rather than raising. Plan for
retries on the agent side based on the error string.
## Related integrations
## Links
- [Resend](https://resend.com)
---
# RevenueCat Integration for AI Agents & Workflows
URL: https://docs.modulex.dev/integrations/tools/revenuecat
Manage in-app subscriptions and entitlements. Retrieve customer subscription status, grant or revoke promotional entitlements, record purchases, update subscriber attributes, and manage Google Play subscription billing.
{/*
GENERATED FILE — do not hand-edit.
Source of truth: modulex-integrations/src/modulex_integrations/tools/revenuecat/
Regenerate with: node scripts/generate-integrations.js
Deferred (future SEO skills — PLAN §8 Extras): keywords, use cases, FAQ,
JSON-LD, branded og:image. Left as stubs on purpose; do not hand-add.
*/}
{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}
## Overview
Add **RevenueCat** to any ModuleX agent or workflow. Manage in-app subscriptions and entitlements against the RevenueCat REST API v1 (`api.revenuecat.com/v1`). Look up subscribers, grant or revoke promotional entitlements, record purchases, update subscriber attributes, and manage Google Play subscription billing.
**Categories**: Finance & Payments · Payments · Subscriptions · **Auth**: API Key · **Actions**: 10
## Authentication
### API Key Authentication
Authenticate using your RevenueCat REST API v1 key
Go to https://app.revenuecat.com and log in
Open Project Settings → API Keys
Create or copy a secret API key (sk_...) for write operations
Paste the API key below
#### Required Credentials
| Field | Description | Required | Format |
|-------|-------------|----------|--------|
| RevenueCat API Key | Your RevenueCat REST API v1 key (secret key recommended) | Yes | `sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
## Available Actions
### Parameters
The app user ID of the subscriber
### Response
```json
{
"$defs": {
"Subscriber": {
"additionalProperties": false,
"description": "A RevenueCat subscriber object.\n\n``subscriptions`` and ``entitlements`` are maps keyed by product /\nentitlement identifier; their values are left as opaque dicts so the\nupstream shape is preserved verbatim.",
"properties": {
"first_seen": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Seen"
},
"last_seen": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Seen"
},
"original_app_user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Original App User Id"
},
"original_application_version": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Original Application Version"
},
"original_purchase_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Original Purchase Date"
},
"management_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Management Url"
},
"subscriptions": {
"additionalProperties": true,
"title": "Subscriptions",
"type": "object"
},
"entitlements": {
"additionalProperties": true,
"title": "Entitlements",
"type": "object"
},
"non_subscriptions": {
"additionalProperties": true,
"title": "Non Subscriptions",
"type": "object"
},
"other_purchases": {
"additionalProperties": true,
"title": "Other Purchases",
"type": "object"
},
"subscriber_attributes": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Subscriber Attributes"
}
},
"title": "Subscriber",
"type": "object"
},
"SubscriberMetadata": {
"additionalProperties": false,
"description": "Summary metadata derived from a subscriber payload.",
"properties": {
"app_user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "App User Id"
},
"first_seen": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Seen"
},
"active_entitlements": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Active Entitlements"
},
"active_subscriptions": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Active Subscriptions"
}
},
"title": "SubscriberMetadata",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"subscriber": {
"anyOf": [
{
"$ref": "#/$defs/Subscriber"
},
{
"type": "null"
}
],
"default": null
},
"metadata": {
"anyOf": [
{
"$ref": "#/$defs/SubscriberMetadata"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GetCustomerOutput",
"type": "object"
}
```
### Parameters
The app user ID of the subscriber to delete
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"deleted": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Deleted"
},
"app_user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "App User Id"
}
},
"required": [
"success"
],
"title": "DeleteCustomerOutput",
"type": "object"
}
```
### Parameters
The app user ID of the subscriber
Store receipt or purchase token: iOS base64 receipt / JWSTransaction, Android purchase token, Amazon receipt, Stripe subscription or Checkout Session ID, Roku transaction ID, or Paddle subscription/transaction ID
Platform of the purchase, sent as the X-Platform header. One of: ios, android, amazon, macos, uikitformac, stripe, roku, paddle
Product identifier or SKU. Required for Google.
Price of the product. Required if you provide a currency.
ISO 4217 currency code. Required if you provide a price.
Deprecated. Triggers configured restore behavior for shared fetch tokens.
Identifier of the offering presented to the customer at purchase time.
Payment mode for the introductory period: pay_as_you_go, pay_up_front, or free_trial.
Introductory price paid (if any).
JSON object of subscriber attributes to set alongside the purchase. Each key maps to {"value": string, "updated_at_ms": number}.
UNIX epoch ms used to resolve attribute conflicts at the request level.
### Response
```json
{
"$defs": {
"Subscriber": {
"additionalProperties": false,
"description": "A RevenueCat subscriber object.\n\n``subscriptions`` and ``entitlements`` are maps keyed by product /\nentitlement identifier; their values are left as opaque dicts so the\nupstream shape is preserved verbatim.",
"properties": {
"first_seen": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Seen"
},
"last_seen": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Seen"
},
"original_app_user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Original App User Id"
},
"original_application_version": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Original Application Version"
},
"original_purchase_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Original Purchase Date"
},
"management_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Management Url"
},
"subscriptions": {
"additionalProperties": true,
"title": "Subscriptions",
"type": "object"
},
"entitlements": {
"additionalProperties": true,
"title": "Entitlements",
"type": "object"
},
"non_subscriptions": {
"additionalProperties": true,
"title": "Non Subscriptions",
"type": "object"
},
"other_purchases": {
"additionalProperties": true,
"title": "Other Purchases",
"type": "object"
},
"subscriber_attributes": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Subscriber Attributes"
}
},
"title": "Subscriber",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"customer": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Customer"
},
"subscriber": {
"anyOf": [
{
"$ref": "#/$defs/Subscriber"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "CreatePurchaseOutput",
"type": "object"
}
```
### Parameters
The app user ID of the subscriber
The entitlement identifier to grant
Deprecated. Provide either duration or end_time_ms (end_time_ms preferred). One of: daily, three_day, weekly, two_week, monthly, two_month, three_month, six_month, yearly, lifetime.
Absolute end time in ms since Unix epoch. Use instead of duration.
Deprecated. Optional start time in ms since Unix epoch, used with duration.
### Response
```json
{
"$defs": {
"Subscriber": {
"additionalProperties": false,
"description": "A RevenueCat subscriber object.\n\n``subscriptions`` and ``entitlements`` are maps keyed by product /\nentitlement identifier; their values are left as opaque dicts so the\nupstream shape is preserved verbatim.",
"properties": {
"first_seen": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Seen"
},
"last_seen": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Seen"
},
"original_app_user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Original App User Id"
},
"original_application_version": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Original Application Version"
},
"original_purchase_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Original Purchase Date"
},
"management_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Management Url"
},
"subscriptions": {
"additionalProperties": true,
"title": "Subscriptions",
"type": "object"
},
"entitlements": {
"additionalProperties": true,
"title": "Entitlements",
"type": "object"
},
"non_subscriptions": {
"additionalProperties": true,
"title": "Non Subscriptions",
"type": "object"
},
"other_purchases": {
"additionalProperties": true,
"title": "Other Purchases",
"type": "object"
},
"subscriber_attributes": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Subscriber Attributes"
}
},
"title": "Subscriber",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"subscriber": {
"anyOf": [
{
"$ref": "#/$defs/Subscriber"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "GrantEntitlementOutput",
"type": "object"
}
```
### Parameters
The app user ID of the subscriber
The entitlement identifier to revoke
### Response
```json
{
"$defs": {
"Subscriber": {
"additionalProperties": false,
"description": "A RevenueCat subscriber object.\n\n``subscriptions`` and ``entitlements`` are maps keyed by product /\nentitlement identifier; their values are left as opaque dicts so the\nupstream shape is preserved verbatim.",
"properties": {
"first_seen": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "First Seen"
},
"last_seen": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Last Seen"
},
"original_app_user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Original App User Id"
},
"original_application_version": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Original Application Version"
},
"original_purchase_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Original Purchase Date"
},
"management_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Management Url"
},
"subscriptions": {
"additionalProperties": true,
"title": "Subscriptions",
"type": "object"
},
"entitlements": {
"additionalProperties": true,
"title": "Entitlements",
"type": "object"
},
"non_subscriptions": {
"additionalProperties": true,
"title": "Non Subscriptions",
"type": "object"
},
"other_purchases": {
"additionalProperties": true,
"title": "Other Purchases",
"type": "object"
},
"subscriber_attributes": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Subscriber Attributes"
}
},
"title": "Subscriber",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"subscriber": {
"anyOf": [
{
"$ref": "#/$defs/Subscriber"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "RevokeEntitlementOutput",
"type": "object"
}
```
### Parameters
An app user ID to retrieve offerings for
X-Platform header value. One of: ios, android, amazon, stripe, roku, paddle. Required for legacy public API keys; ignored with app-specific keys.
### Response
```json
{
"$defs": {
"Offering": {
"additionalProperties": false,
"description": "A single offering configured for the project.",
"properties": {
"identifier": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Identifier"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Description"
},
"packages": {
"items": {
"$ref": "#/$defs/OfferingPackage"
},
"title": "Packages",
"type": "array"
}
},
"title": "Offering",
"type": "object"
},
"OfferingPackage": {
"additionalProperties": false,
"description": "A single package inside an offering.",
"properties": {
"identifier": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Identifier"
},
"platform_product_identifier": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Platform Product Identifier"
}
},
"title": "OfferingPackage",
"type": "object"
},
"OfferingsMetadata": {
"additionalProperties": false,
"description": "Summary metadata for a list-offerings response.",
"properties": {
"count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Count"
},
"current_offering_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Current Offering Id"
}
},
"title": "OfferingsMetadata",
"type": "object"
}
},
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"current_offering_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Current Offering Id"
},
"offerings": {
"items": {
"$ref": "#/$defs/Offering"
},
"title": "Offerings",
"type": "array"
},
"metadata": {
"anyOf": [
{
"$ref": "#/$defs/OfferingsMetadata"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"success"
],
"title": "ListOfferingsOutput",
"type": "object"
}
```
### Parameters
The app user ID of the subscriber
JSON object of attributes to set. Each key maps to an object with "value" (string; null or empty deletes the attribute) and "updated_at_ms" (Unix epoch ms used for conflict resolution — required).
### Response
```json
{
"additionalProperties": false,
"properties": {
"success": {
"title": "Success",
"type": "boolean"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Error"
},
"updated": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Updated"
},
"app_user_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "App User Id"
}
},
"required": [
"success"
],
"title": "UpdateSubscriberAttributesOutput",
"type": "object"
}
```
### Parameters
The app user ID of the subscriber
The Google Play product identifier of