One open source package with 12 shared tasks for current testimonials, project links, reviewed imports/invites and private bounded exports.
This free Senja MCP server and CLI connects your AI to the testimonials and project assets you choose. Find existing customer proof, inspect form/widget links, and apply only the testimonial changes or invite batches you explicitly approve.
The same tasks run as local MCP tools for Codex and compatible clients, or as CLI commands for scripts and agents. Senja's official hosted MCP already supports search, asset links and invites; this companion adds the documented local interfaces and workflows.
Key takeaways
What is the Senja MCP server & CLI?
It is one open source Node package with a local stdio MCP server, task CLI and bundled desktop extension. Both interfaces invoke the same native handlers, schemas, project selection and write guard. The public REST subset is seven reviewed endpoints, not every Senja UI feature.
What can you ask it?
Try askingFind five approved testimonials about onboarding from the project I selected.
Read my form and widget links before I choose the intended asset.
Review these exact testimonial tag changes before applying the batch I approve.
Save a bounded private testimonial export to a new file without echoing customer records into chat.
Inspect the intended form and recipients before proposing an invite sequence.
Install and connect
One package has 12 shared tools, CLI and local stdio MCP binaries, and a released desktop archive. Node 22+ is required.
Requirements
Install Node, then check node --version and npm --version in the runtime your client uses. Windows users may need npm.cmd if PowerShell policy blocks npm.ps1. No sudo or weakening execution policy is required. GUI apps, containers and remote runtimes need their own private settings and readable files.
CLI
bashnpm install -g @thenavidm/senja-mcp-cli@latest
senja-cli --version
senja-cli tools
senja-cli list-testimonials --help
senja-cli schema list-testimonials
A temporary alternative is npx -y --package @thenavidm/senja-mcp-cli@latest senja-cli tools. Make the shipped SKILL.md available in your agent's supported private skill location; npm does not register skills automatically.
Private project setup
Choose the intended project and private API key
- Sign into Senja and select the project whose testimonials you intend to use. Confirm the project before copying any credential. A key is a private project connection, not a general public widget ID.
- Open Automate and copy that project's API key into a private runtime setting. Current REST API documentation covers Free, Starter and Pro. Native plan features and account policies remain separate; the wrapper does not bypass them.
- Configure exactly one of SENJA_API_KEY or SENJA_TOKEN_FILE. The latter is an absolute, regular, non-symlink, token-only file outside repositories, at most 64 KiB. The client sends Authorization: Bearer; do not prefix the setting with Bearer or use your login password.
- On macOS/Linux restrict the file to your owner with mode 0600 and its parent directory to your owner. On Windows restrict file and parent-directory ACLs separately. POSIX modes do not establish Windows privacy. Each server runtime must be able to read its own file; a GUI, Docker or remote host does not inherit a different terminal's environment automatically.
- Run senja-cli doctor for local configuration. When you deliberately want an authenticated read, run doctor --network: it requests GET /testimonials?limit=1 and prints count/verification metadata, not customer records. This proves one project read, not ownership, permission for every endpoint, successful email delivery or an approved mutation.
The package does not load .env files, import browser cookies, create keys, connect OAuth or rotate credentials. login prints these setup instructions only. Keep resolved secrets out of code, screenshots, public issues, version control and AI prompts.
Project profiles and revocation
SENJA_ACCOUNTS is a private JSON array of unique {name,api_key,token_file} profiles. Use one credential method per profile. SENJA_DEFAULT_ACCOUNT selects the default label and --account selects an exact label. An incomplete named profile never inherits a global key, another project or an official hosted session after a missing credential or 401/403.
list_accounts returns labels/default/auth/source only, without keys, token paths, native project identity or network traffic. Token-only files cache until restart. Changing a file while a process is running does not rotate its cached connection.
To revoke a key, use the intended project's Automate > Regenerate API Key as its Admin/Owner, update every dependent private integration and restart its processes. The provider says the old key stops working after a short transition. Official hosted MCP authorization is a separate connection. Removing this package does not undo testimonial edits, publish approval, permanent deletion, emailed invites, follow-up sequences or existing exports.
Effects and local limits
There is no universal provider quota invented here. Local spacing defaults to 250 ms and request timeout 30 seconds; other processes share native project quotas. Bodies cap at 1 MiB and responses at 5 MiB. No automatic retry, redirect following or media download occurs. A failed write can have an unknown outcome; inspect native state before any explicit repeat.
send_invites uses a real forms[].id from list_links and that form's existing email/follow-up sequence. It is not a local draft, arbitrary email editor or test-send command. Its local 100-recipient cap is not a documented native quota. Receipt sent/skipped values do not prove delivered messages or consent. Only send to the actual approved recipients and purpose.
Codex
Codex is the current validation priority. Private token paths must exist in the process or remote environment where the server runs.
bashcodex mcp add senja -- npx -y @thenavidm/senja-mcp-cli@latest
codex mcp list
Account credentials must reach the server through private environment settings. codex mcp add --env NAME=value stores values in your local config, so never commit that config or put secrets in a shared command. In TOML, the equivalent server is:
toml[mcp_servers.senja]
command = "npx"
args = ["-y", "@thenavidm/senja-mcp-cli@latest"]
env_vars = ["SENJA_API_KEY", "SENJA_TOKEN_FILE", "SENJA_ACCOUNTS", "SENJA_DEFAULT_ACCOUNT", "SENJA_READ_ONLY", "SENJA_ALLOW_DESTRUCTIVE"]
env_vars forwards those names from the environment available to Codex. If that environment does not contain them, configure private env settings locally. Codex can also call the CLI directly with SKILL.md and --agent output.
Claude Code
For a user-scoped connection, after privately configuring credentials:
bashclaude mcp add --scope user senja -- npx -y @thenavidm/senja-mcp-cli@latest
claude mcp list
Use the client's private local environment settings for the account variable if they are not inherited. Claude's -e NAME=value registration option writes values into its config; only use it locally through your secret manager, with no shared command transcript. Never place credentials in a project .mcp.json. Reconnect and ask Claude to verify credentials.
Alternatively install the CLI, make SKILL.md available to Claude, and use shell commands. Registering both surfaces is optional.
Claude Desktop
Install the .mcpb extension
- Download
senja-2.0.0.mcpbfrom GitHub Releases. - In a supported Claude Desktop build, open Settings > Extensions > Advanced settings > Install Extension… and select it.
- Enter a private project API key in the sensitive setting, OR an absolute private token-only file path. Leave the unused method empty. Requests use Authorization: Bearer. Named profiles require private manual runtime settings.
- Enable read-only if you want only the 6 read operations. Reconnect and verify the intended project with one deliberate read.
The bundle includes production dependencies and no credentials. Use a regular private token-only file if you prefer file-based credentials. The manifest requires Node 22 or newer from a compatible host. Organization policy may restrict custom extensions. Manual bundle updates require installing the new version; no automatic directory updates are promised. GUI installation remains unverified separately from archive/protocol checks.
Manual config
Open Settings > Developer > Edit Config, or use your platform's config file:
| OS | Typical config path |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
| Linux | ~/.config/Claude/claude_desktop_config.json; confirm the location through Edit Config in your installed build |
json{
"mcpServers": {
"senja": {
"command": "npx",
"args": ["-y", "@thenavidm/senja-mcp-cli@latest"],
"env": {
"SENJA_API_KEY": "YOUR_PRIVATE_API_KEY",
"SENJA_TOKEN_FILE": ""
}
}
}
}
Replace the placeholders only in your private file. Merge the server entry into an existing mcpServers object instead of replacing other integrations. Fully quit and reopen Claude Desktop. Do not enable an extension and a manual entry with the same name; choose one route.
If a Windows launcher cannot execute npx directly, use "command": "cmd" with "args": ["/c", "npx", "-y", "@thenavidm/senja-mcp-cli@latest"]. An absolute node executable and installed dist/index.js path also avoids launcher/PATH problems.
Cursor
Use private user settings at ~/.cursor/mcp.json, or Settings > Tools & MCP. Cursor documents environment interpolation and envFile support.
json{
"mcpServers": {
"senja": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@thenavidm/senja-mcp-cli@latest"],
"env": {
"SENJA_API_KEY": "${env:SENJA_API_KEY}",
"SENJA_TOKEN_FILE": "${env:SENJA_TOKEN_FILE}"
}
}
}
}
The environment values must exist for the Cursor process. If you use envFile, keep that file private and outside version control. A project's .cursor/mcp.json must not contain actual credentials. Reconnect the server after saving.
VS Code and Copilot
Use MCP: Open User Configuration. VS Code uses servers and secure inputs, rather than a mcpServers root:
json{
"inputs": [
{"type": "promptString", "id": "senja-api-token", "description": "Senja API key (leave empty for a private token file)", "password": true},
{"type": "promptString", "id": "senja-token-file", "description": "Optional private token-file path (leave empty for API key)"}
],
"servers": {
"senja": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@thenavidm/senja-mcp-cli@latest"],
"env": {
"SENJA_API_KEY": "${input:senja-api-token}",
"SENJA_TOKEN_FILE": "${input:senja-token-file}"
}
}
}
}
Start Senja through the MCP controls, approve trust if prompted, and enter credentials in the private input prompts. Workspace .vscode/mcp.json may contain this placeholder-only structure, but never resolved secret values. Remote development runs the server in the selected remote environment, so local file paths refer to that environment.
Windsurf
Open Cascade's MCP settings or edit the private user file ~/.codeium/windsurf/mcp_config.json. Use the Claude Desktop manual mcpServers block above with your locally configured env values. See Windsurf's current MCP documentation. Restart or reconnect Senja in Cascade; project files must not contain secrets.
Zed
Open Settings > AI > MCP Servers > Add Server > Add Local Server, or your user settings file. Zed uses context_servers:
json{
"context_servers": {
"senja": {
"command": "npx",
"args": ["-y", "@thenavidm/senja-mcp-cli@latest"],
"env": {
"SENJA_API_KEY": "YOUR_PRIVATE_API_KEY",
"SENJA_TOKEN_FILE": ""
}
}
}
}
Enter actual values only in private user settings. Check the active-server indicator before prompting. Do not wrap command and args inside a nested command object from older Zed examples.
Gemini CLI
Merge the Claude Desktop manual mcpServers block into your private ~/.gemini/settings.json. Configure the private credential values locally, then restart Gemini CLI and inspect /mcp. See Gemini CLI's MCP configuration. Its project settings must not contain real credentials. You can instead use the CLI from an agent shell.
Other local stdio clients use the same command and arguments, adapted to their config format. A client that only accepts a remote MCP URL cannot connect directly: this package does not ship a public HTTP listener. ChatGPT's remote connector setup is not a substitute for local stdio installation.
Docker
Build locally from the reviewed source; no prebuilt registry image is claimed:
bashgit clone https://github.com/thenavidm/senja-mcp-cli.git
cd senja-mcp-cli
docker build -t senja-mcp-cli .
docker run --rm -i -e SENJA_API_KEY senja-mcp-cli
Cline and other local MCP clients
Use the client's Add MCP server flow with command npx, arguments -y and @thenavidm/senja-mcp-cli@latest, stdio transport, and private local SENJA_API_KEY or SENJA_TOKEN_FILE settings. UI names depend on the installed client. Reconnect and discover tools before an account call. Browser-only clients need a remote HTTPS connector; use Senja's official server rather than this local stdio command.
Verify
bashsenja-cli --version
senja-cli tools
senja-cli list-accounts --agent
senja-cli doctor
senja-cli doctor --network
senja-cli list-testimonials --limit 1 --agent --select total,testimonials.id
Only the final two commands intentionally contact Senja. The one-item example may return a private ID; use doctor --network if you only need verification metadata. Never create, approve, delete or email a testimonial merely to test installation. Fixtures/protocol discovery, actual provider outcomes, desktop GUI installation and completed Codex usage measurements are distinct checks.
Several projects
SENJA_ACCOUNTS is a private JSON array of unique {name,api_key,token_file} profiles. Use one credential method per profile. SENJA_DEFAULT_ACCOUNT selects the default label and --account selects an exact label. An incomplete named profile never inherits a global key, another project or an official hosted session after a missing credential or 401/403.
list_accounts returns labels/default/auth/source only, without keys, token paths, native project identity or network traffic. Token-only files cache until restart. Changing a file while a process is running does not rotate its cached connection.
To revoke a key, use the intended project's Automate > Regenerate API Key as its Admin/Owner, update every dependent private integration and restart its processes. The provider says the old key stops working after a short transition. Official hosted MCP authorization is a separate connection. Removing this package does not undo testimonial edits, publish approval, permanent deletion, emailed invites, follow-up sequences or existing exports.
Updates and removal
Restart npx@latest registrations to resolve the current version. Update a global CLI with npm install -g @thenavidm/senja-mcp-cli@latest and install a new .mcpb manually. Remove only the requested registration/skill/global package/extension, and revoke the intended project key separately. Uninstalling does not undo proof changes or send history.
bashnpm install -g @thenavidm/senja-mcp-cli@latest
senja-cli --version
# Removal only when requested
npm uninstall -g @thenavidm/senja-mcp-cli
Troubleshooting
| Symptom | Check |
|---|---|
| No binary or Node error | Node 22+, npm/PATH in the actual GUI/remote runtime; npm.cmd if Windows policy blocks npm.ps1 |
| Exit10 or unknown profile | Exact profile name and one private key/file; no fallback exists |
| Unreadable token file | Absolute owner-private regular non-symlink file under 64 KiB; restart after replacing it |
| 401/403 | Selected project/key/permissions and revocation; official hosted auth is separate |
| Old sort/per_page/language rejected | Use sort date/rating, order asc/desc, limit and lang |
| PATCH edit refused | Only approved/add_tags/remove_tags; use dashboard for text/customer/rating edits |
| Cannot send or delete | Explicit --confirm and local policy; inspect native permissions and real purpose |
| Invites skipped | Inspect native sent/skipped receipt and existing form sequence; do not blindly repeat |
| Export stopped at cap | Inspect page/offset/limit and resume to a different new private file |
| Existing output file | Choose a new file; never remove/overwrite unrelated data |
| Review hash mismatch | Preview the exact unchanged order/inputs/profile/schema again |
| 429 or uncertain write result | No automatic retry; inspect native state and available rate-limit guidance |
| Browser-only client | Use official hosted MCP; local stdio needs a supported server runtime |
| Desktop GUI blocked | Organization/client support and Node 22 runtime; archive discovery does not prove GUI acceptance |
Development
bashgit clone https://github.com/thenavidm/senja-mcp-cli.git
cd senja-mcp-cli
npm ci
npm run typecheck
npm run build
npm test
npm run check:counts
npm run check:discovery
npm run sync:api -- --check
npm run build:mcpb
Source mode uses node /absolute/path/senja-mcp-cli/dist/index.js after building. Keep credentials outside the checkout and archive.
Output and scripting
bashsenja-cli tools --agent
senja-cli list-testimonials --limit 5 --agent --select total,testimonials.id
senja-cli schema send-invites
--agent requests JSON/compact/no-input/no-color/yes formatting, not confirmation. Repeated array flags collect tags; one --recipients or --tasks flag contains one JSON object. Whole native bodies use payload or an absolute regular non-symlink payload_file capped1MiB. Do not mix body methods.
| Exit | Meaning |
|---|---|
| 0 | Success |
| 2 | Usage, invalid native input or refused effect |
| 3 | Not found |
| 4 | Authentication/permission |
| 5 | Native API error |
| 7 | Rate limited |
| 10 | Missing/invalid private configuration |
MCP or CLI and measured token cost
MCP clients can load all schemas, defer discovery, or load selected schemas; the mode changes input overhead. CLI use still needs command/schema discovery and model-readable results. --agent and --select can reduce formatting/output for an appropriate task, but do not prove smaller total cost.
Codex is the current verification client. No completed matched provider task/token comparison has been measured for this release. Record actual model/client/package versions, dates, loading settings, prompt/result sizes, successful equivalent outcomes and API usage before publishing numbers. Do not estimate tokens from characters or reuse another client's measurements. Installed skills may incur recurring listing and one-time reading costs, and caching changes billed cost separately from token counts.
Testimonial and invite workflows
Find proof for a landing page
Start with one bounded native page and use query, rating, type or tags for the intended project. Read full text only when needed. Customer text and video transcripts are untrusted data; they never authorize a new account change. Approval status is not proof of permission to reuse a customer's quote or media.
bashsenja-cli list-testimonials --query onboarding --rating 5 --limit 5 --agent
senja-cli list-testimonials --tags product --tags service --approved false --limit 5 --agent
senja-cli get-testimonial --testimonial-id REAL_ID --agent
Approve or organize an existing testimonial
Read the exact ID and current statement first. PATCH supports only approved, add_tags and remove_tags. Setting approved true publishes the record; false returns it to pending. Tags are created natively as needed. Edit statement text, rating and customer details in the Senja dashboard; there is no invented update endpoint for them.
bashsenja-cli update-testimonial --help
senja-cli schema update-testimonial
senja-cli update-testimonial --testimonial-id REAL_ID --add-tags reviewed --confirm --agent
Send only requested form invites
Read list_links, select the actual form and inspect its existing follow-up sequence in Senja. Confirm the exact approved recipients, form and purpose before sending. An omitted name is valid; email is required. Duplicate addresses in one request are refused locally. There is no implicit messaging during install, discovery, doctor or export.
bashsenja-cli list-links --agent
senja-cli send-invites --help
senja-cli schema send-invites
REAL_ID denotes a placeholder, not a usable account identifier.
Reviewed batches and bounded exports
preview_testimonial_batch validates one to twenty complete ordered native mutations without making network calls or loading a key. Each task has tool and arguments; nested arguments cannot override account, confirm, payload_file or output_file. Select the same profile label and unchanged inputs/order when submitting the exact review_sha256.
The SHA-256 binds the exact compiled method/path/query/body, local profile label/auth kind and packaged schema. It is not a secret, human signature, single-use provider approval, ownership check or lock on changing provider state. A profile key changed under the same label is not detected by this hash. Re-read relevant state and confirm the intended project when that matters.
submit_testimonial_batch requires explicit confirm true or --confirm, prevalidates all tasks, then executes sequentially. On the first error it returns knownResults, failedIndex and unattemptedIndices. No retry, rollback or automatic continuation occurs. A failed request can already have taken effect. Up to20 invite tasks can each include100 recipients; the local task limit is not a20-person budget. Review the full recipient list and follow-up consequences.
bashsenja-cli preview-testimonial-batch --help
senja-cli schema submit-testimonial-batch
export_testimonials reserves one absolute new private file exclusively, performs only the bounded requested list pages, and returns path/bytes/SHA-256 and receipt metadata. Defaults: 10 pages, 1,000 items, native page size 100. Local caps: 100 pages, 10,000 items and 5 MiB final JSON. A short native page signals exhaustion within the selected filters at that moment. Native total counts the current page, not the entire project.
When a local cap stops the walk, continuation reports page, offset and limit. Resume with that page, identical filters/page size and start_offset. Page changes can cause shifted records; no atomic snapshot, complete backup or deduplication guarantee is made. A second resume writes a different new file; it never appends to or overwrites the earlier export. Review/de-duplicate native IDs when combining evolving pages.
Failure removes only the file this export newly created. Media URLs and transcript metadata remain JSON data; this package never follows or downloads them. Read-only mode refuses file output too. Restrict parent-directory privacy and Windows ACLs separately.
bashsenja-cli export-testimonials --help
senja-cli schema export-testimonials
Every tool and argument
These task summaries come from the shipped server discovery. The complete argument tables and native schemas follow.
Testimonials
list_testimonials- What it does
- Read one native page with exact current search, tag, approval, language and date/rating filters.
- Kind
- Read/helper
get_testimonial- What it does
- Read one exact testimonial, including native video metadata and public/dashboard links.
- Kind
- Read/helper
create_testimonial- What it does
- Create one text/video testimonial from an authorized existing customer statement.
- Kind
- Confirmed operation
update_testimonial- What it does
- Change only native approval status and tag additions/removals.
- Kind
- Confirmed operation
delete_testimonial- What it does
- Permanently delete exactly the requested testimonial.
- Kind
- Confirmed operation
Project Links
list_links- What it does
- Read native form, widget, Wall of Love, quick-link, case-study and sizzle-reel groups with their IDs and URLs.
- Kind
- Read/helper
Invites
send_invites- What it does
- Send email invites using a selected form and its existing follow-up sequence.
- Kind
- Confirmed operation
Local Workflows
list_accounts- What it does
- Local profile labels/default/auth method only.
- Kind
- Read/helper
get_operation_schema- What it does
- Local reviewed method/path/query/body schema and provenance for one native tool.
- Kind
- Read/helper
preview_testimonial_batch- What it does
- Local validation and SHA-256 of exact ordered testimonial/import/invite work, selected profile label and reviewed schema.
- Kind
- Read/helper
submit_testimonial_batch- What it does
- Confirmed one-to-twenty ordered testimonial/import/invite tasks.
- Kind
- Confirmed operation
export_testimonials- What it does
- Confirmed paginated GET export to an exclusive new0600 JSON file.
- Kind
- Confirmed operation
list_testimonials
Read one native page with exact current search, tag, approval, language and date/rating filters.
sort- Type
- string
- Required
- Optional
- Meaning and constraints
- Native sort field; direction uses order. {"enum": ["date", "rating"]}
order- Type
- string
- Required
- Optional
- Meaning and constraints
- {"enum": ["asc", "desc"]}
approved- Type
- boolean
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
rating- Type
- integer
- Required
- Optional
- Meaning and constraints
- {"minimum": 1, "maximum": 5}
type- Type
- string
- Required
- Optional
- Meaning and constraints
- {"enum": ["text", "video"]}
integration- Type
- string
- Required
- Optional
- Meaning and constraints
- {"enum": ["twitter", "product_hunt", "google", "facebook", "reddit", "capterra", "g2", "linkedin", "app_store", "trustpilot", "shopify", "play_store", "yelp", "slack", "discord", "apple_podcasts", "telegram", "whatsapp", "instagram", "youtube", "tiktok", "appsumo", "amazon", "zillow", "udemy", "chrome_web_store", "airbnb", "skillshare", "realtor", "sourceforge", "whop", "wordpress", "fiverr", "homestars", "web_page"]}
tags- Type
- array
- Required
- Optional
- Meaning and constraints
- {"maxItems": 100}
query- Type
- string
- Required
- Optional
- Meaning and constraints
- Native full-text search, including customer name/email; output may contain personal data.
lang- Type
- string
- Required
- Optional
- Meaning and constraints
- Native ISO 639 language selector.
limit- Type
- integer
- Required
- Optional
- Meaning and constraints
- Native page size. total counts only the current page. {"minimum": 1, "maximum": 1000}
page- Type
- integer
- Required
- Optional
- Meaning and constraints
- {"minimum": 1}
account- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact configured private account profile label; not a tenant or provider account ID.
bashsenja-cli list-testimonials --help
senja-cli schema list-testimonials
json{
"type": "object",
"properties": {
"sort": {
"type": "string",
"enum": [
"date",
"rating"
],
"description": "Native sort field; direction uses order."
},
"order": {
"type": "string",
"enum": [
"asc",
"desc"
]
},
"approved": {
"type": "boolean"
},
"rating": {
"type": "integer",
"minimum": 1,
"maximum": 5
},
"type": {
"type": "string",
"enum": [
"text",
"video"
]
},
"integration": {
"type": "string",
"enum": [
"twitter",
"product_hunt",
"google",
"facebook",
"reddit",
"capterra",
"g2",
"linkedin",
"app_store",
"trustpilot",
"shopify",
"play_store",
"yelp",
"slack",
"discord",
"apple_podcasts",
"telegram",
"whatsapp",
"instagram",
"youtube",
"tiktok",
"appsumo",
"amazon",
"zillow",
"udemy",
"chrome_web_store",
"airbnb",
"skillshare",
"realtor",
"sourceforge",
"whop",
"wordpress",
"fiverr",
"homestars",
"web_page"
]
},
"tags": {
"type": "array",
"maxItems": 100,
"items": {
"type": "string",
"minLength": 1,
"description": "Nonempty tag name."
}
},
"query": {
"type": "string",
"minLength": 1,
"description": "Native full-text search, including customer name/email; output may contain personal data.",
"maxLength": 10000
},
"lang": {
"type": "string",
"minLength": 1,
"description": "Native ISO 639 language selector.",
"maxLength": 10
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 1000,
"description": "Native page size. total counts only the current page."
},
"page": {
"type": "integer",
"minimum": 1
},
"account": {
"type": "string",
"description": "Exact configured private account profile label; not a tenant or provider account ID."
}
},
"required": [],
"additionalProperties": false
}
Native request: GET /testimonials. No native JSON body.
json{
"name": "list_testimonials",
"method": "GET",
"path": "/testimonials",
"title": "List testimonials",
"description": "Read one native page with exact current search, tag, approval, language and date/rating filters.",
"group": "testimonials",
"risk": "read",
"params": [
{
"name": "sort",
"key": "sort",
"schema": {
"type": "string",
"enum": [
"date",
"rating"
],
"description": "Native sort field; direction uses order."
},
"in": "query",
"required": false,
"style": "form",
"explode": true
},
{
"name": "order",
"key": "order",
"schema": {
"type": "string",
"enum": [
"asc",
"desc"
]
},
"in": "query",
"required": false,
"style": "form",
"explode": true
},
{
"name": "approved",
"key": "approved",
"schema": {
"type": "boolean"
},
"in": "query",
"required": false,
"style": "form",
"explode": true
},
{
"name": "rating",
"key": "rating",
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 5
},
"in": "query",
"required": false,
"style": "form",
"explode": true
},
{
"name": "type",
"key": "type",
"schema": {
"type": "string",
"enum": [
"text",
"video"
]
},
"in": "query",
"required": false,
"style": "form",
"explode": true
},
{
"name": "integration",
"key": "integration",
"schema": {
"type": "string",
"enum": [
"twitter",
"product_hunt",
"google",
"facebook",
"reddit",
"capterra",
"g2",
"linkedin",
"app_store",
"trustpilot",
"shopify",
"play_store",
"yelp",
"slack",
"discord",
"apple_podcasts",
"telegram",
"whatsapp",
"instagram",
"youtube",
"tiktok",
"appsumo",
"amazon",
"zillow",
"udemy",
"chrome_web_store",
"airbnb",
"skillshare",
"realtor",
"sourceforge",
"whop",
"wordpress",
"fiverr",
"homestars",
"web_page"
]
},
"in": "query",
"required": false,
"style": "form",
"explode": true
},
{
"name": "tags",
"key": "tags",
"schema": {
"type": "array",
"maxItems": 100,
"items": {
"type": "string",
"minLength": 1,
"description": "Nonempty tag name."
}
},
"in": "query",
"required": false,
"style": "form",
"explode": true
},
{
"name": "query",
"key": "query",
"schema": {
"type": "string",
"minLength": 1,
"description": "Native full-text search, including customer name/email; output may contain personal data.",
"maxLength": 10000
},
"in": "query",
"required": false,
"style": "form",
"explode": true
},
{
"name": "lang",
"key": "lang",
"schema": {
"type": "string",
"minLength": 1,
"description": "Native ISO 639 language selector.",
"maxLength": 10
},
"in": "query",
"required": false,
"style": "form",
"explode": true
},
{
"name": "limit",
"key": "limit",
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 1000,
"description": "Native page size. total counts only the current page."
},
"in": "query",
"required": false,
"style": "form",
"explode": true
},
{
"name": "page",
"key": "page",
"schema": {
"type": "integer",
"minimum": 1
},
"in": "query",
"required": false,
"style": "form",
"explode": true
}
],
"bodySchema": null,
"bodyRequired": false,
"privateOutput": false
}
get_testimonial
Read one exact testimonial, including native video metadata and public/dashboard links.
testimonial_id- Type
- string
- Required
- Required
- Meaning and constraints
- Exact testimonial ID. No slash, traversal or arbitrary URL.
account- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact configured private account profile label; not a tenant or provider account ID.
bashsenja-cli get-testimonial --help
senja-cli schema get-testimonial
json{
"type": "object",
"properties": {
"testimonial_id": {
"type": "string",
"minLength": 1,
"description": "Exact testimonial ID. No slash, traversal or arbitrary URL."
},
"account": {
"type": "string",
"description": "Exact configured private account profile label; not a tenant or provider account ID."
}
},
"required": [
"testimonial_id"
],
"additionalProperties": false
}
Native request: GET /testimonials/{testimonial_id}. No native JSON body.
json{
"name": "get_testimonial",
"method": "GET",
"path": "/testimonials/{testimonial_id}",
"title": "Read one testimonial",
"description": "Read one exact testimonial, including native video metadata and public/dashboard links.",
"group": "testimonials",
"risk": "read",
"params": [
{
"name": "testimonial_id",
"key": "testimonial_id",
"schema": {
"type": "string",
"minLength": 1,
"description": "Exact testimonial ID. No slash, traversal or arbitrary URL."
},
"in": "path",
"required": true,
"style": "form",
"explode": true
}
],
"bodySchema": null,
"bodyRequired": false,
"privateOutput": false
}
create_testimonial
Create one text/video testimonial from an authorized existing customer statement. Explicit approval is required.
title- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
text- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
customer_name- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
customer_company- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
customer_tagline- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
customer_username- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
form_id- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
url- Type
- string
- Required
- Optional
- Meaning and constraints
- HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}
thumbnail_url- Type
- string
- Required
- Optional
- Meaning and constraints
- HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}
customer_avatar- Type
- string
- Required
- Optional
- Meaning and constraints
- HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}
customer_company_logo- Type
- string
- Required
- Optional
- Meaning and constraints
- HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}
customer_url- Type
- string
- Required
- Optional
- Meaning and constraints
- HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}
video_url- Type
- string
- Required
- Optional
- Meaning and constraints
- HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}
type- Type
- string
- Required
- Optional
- Meaning and constraints
- {"enum": ["text", "video"]}
customer_email- Type
- string
- Required
- Optional
- Meaning and constraints
- {"format": "email"}
rating- Type
- integer
- Required
- Optional
- Meaning and constraints
- {"minimum": 1, "maximum": 5}
date- Type
- string
- Required
- Optional
- Meaning and constraints
- {"format": "date-time"}
approved- Type
- boolean
- Required
- Optional
- Meaning and constraints
- Explicitly true publishes the testimonial; false keeps it pending.
integration- Type
- string
- Required
- Optional
- Meaning and constraints
- {"enum": ["twitter", "product_hunt", "google", "facebook", "reddit", "capterra", "g2", "linkedin", "app_store", "trustpilot", "shopify", "play_store", "yelp", "slack", "discord", "apple_podcasts", "telegram", "whatsapp", "instagram", "youtube", "tiktok", "appsumo", "amazon", "zillow", "udemy", "chrome_web_store", "airbnb", "skillshare", "realtor", "sourceforge", "whop", "wordpress", "fiverr", "homestars", "web_page"]}
tags- Type
- array
- Required
- Optional
- Meaning and constraints
- {"maxItems": 100}
media- Type
- array
- Required
- Optional
- Meaning and constraints
- {"maxItems": 100}
media[].alt- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
media[].url- Type
- string
- Required
- Required
- Meaning and constraints
- {"format": "uri"}
media[].type- Type
- string
- Required
- Required
- Meaning and constraints
- {"enum": ["image", "video"]}
account- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact configured private account profile label; not a tenant or provider account ID.
confirm- Type
- boolean
- Required
- Optional
- Meaning and constraints
- Must be true for the requested mutation or exclusive private output file.
payload- Type
- object
- Required
- Optional
- Meaning and constraints
- Complete native JSON body; do not mix with body flags or payload_file. Arrays use repeated JSON object flags or a whole native array in a private file.
payload.title- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
payload.text- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
payload.customer_name- Type
- string
- Required
- Required
- Meaning and constraints
- Exact native/schema value
payload.customer_company- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
payload.customer_tagline- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
payload.customer_username- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
payload.form_id- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
payload.url- Type
- string
- Required
- Optional
- Meaning and constraints
- HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}
payload.thumbnail_url- Type
- string
- Required
- Optional
- Meaning and constraints
- HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}
payload.customer_avatar- Type
- string
- Required
- Optional
- Meaning and constraints
- HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}
payload.customer_company_logo- Type
- string
- Required
- Optional
- Meaning and constraints
- HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}
payload.customer_url- Type
- string
- Required
- Optional
- Meaning and constraints
- HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}
payload.video_url- Type
- string
- Required
- Optional
- Meaning and constraints
- HTTPS URL without embedded credentials; provider retrieves media where supported. {"format": "uri"}
payload.type- Type
- string
- Required
- Required
- Meaning and constraints
- {"enum": ["text", "video"]}
payload.customer_email- Type
- string
- Required
- Optional
- Meaning and constraints
- {"format": "email"}
payload.rating- Type
- integer
- Required
- Optional
- Meaning and constraints
- {"minimum": 1, "maximum": 5}
payload.date- Type
- string
- Required
- Optional
- Meaning and constraints
- {"format": "date-time"}
payload.approved- Type
- boolean
- Required
- Optional
- Meaning and constraints
- Explicitly true publishes the testimonial; false keeps it pending.
payload.integration- Type
- string
- Required
- Optional
- Meaning and constraints
- {"enum": ["twitter", "product_hunt", "google", "facebook", "reddit", "capterra", "g2", "linkedin", "app_store", "trustpilot", "shopify", "play_store", "yelp", "slack", "discord", "apple_podcasts", "telegram", "whatsapp", "instagram", "youtube", "tiktok", "appsumo", "amazon", "zillow", "udemy", "chrome_web_store", "airbnb", "skillshare", "realtor", "sourceforge", "whop", "wordpress", "fiverr", "homestars", "web_page"]}
payload.tags- Type
- array
- Required
- Optional
- Meaning and constraints
- {"maxItems": 100}
payload.media- Type
- array
- Required
- Optional
- Meaning and constraints
- {"maxItems": 100}
payload.media[].alt- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
payload.media[].url- Type
- string
- Required
- Required
- Meaning and constraints
- {"format": "uri"}
payload.media[].type- Type
- string
- Required
- Required
- Meaning and constraints
- {"enum": ["image", "video"]}
payload_file- Type
- string
- Required
- Optional
- Meaning and constraints
- Absolute regular non-symlink JSON body file, at most 1 MiB. Cannot mix with payload/body flags.
bashsenja-cli create-testimonial --help
senja-cli schema create-testimonial
json{
"type": "object",
"properties": {
"title": {
"type": "string",
"minLength": 1,
"description": ""
},
"text": {
"type": "string",
"minLength": 1,
"description": ""
},
"customer_name": {
"type": "string",
"minLength": 1,
"description": ""
},
"customer_company": {
"type": "string",
"minLength": 1,
"description": ""
},
"customer_tagline": {
"type": "string",
"minLength": 1,
"description": ""
},
"customer_username": {
"type": "string",
"minLength": 1,
"description": ""
},
"form_id": {
"type": "string",
"minLength": 1,
"description": ""
},
"url": {
"type": "string",
"minLength": 1,
"description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
"format": "uri"
},
"thumbnail_url": {
"type": "string",
"minLength": 1,
"description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
"format": "uri"
},
"customer_avatar": {
"type": "string",
"minLength": 1,
"description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
"format": "uri"
},
"customer_company_logo": {
"type": "string",
"minLength": 1,
"description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
"format": "uri"
},
"customer_url": {
"type": "string",
"minLength": 1,
"description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
"format": "uri"
},
"video_url": {
"type": "string",
"minLength": 1,
"description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
"format": "uri"
},
"type": {
"type": "string",
"enum": [
"text",
"video"
]
},
"customer_email": {
"type": "string",
"minLength": 1,
"description": "",
"format": "email"
},
"rating": {
"type": "integer",
"minimum": 1,
"maximum": 5
},
"date": {
"type": "string",
"minLength": 1,
"description": "",
"format": "date-time"
},
"approved": {
"type": "boolean",
"description": "Explicitly true publishes the testimonial; false keeps it pending."
},
"integration": {
"type": "string",
"enum": [
"twitter",
"product_hunt",
"google",
"facebook",
"reddit",
"capterra",
"g2",
"linkedin",
"app_store",
"trustpilot",
"shopify",
"play_store",
"yelp",
"slack",
"discord",
"apple_podcasts",
"telegram",
"whatsapp",
"instagram",
"youtube",
"tiktok",
"appsumo",
"amazon",
"zillow",
"udemy",
"chrome_web_store",
"airbnb",
"skillshare",
"realtor",
"sourceforge",
"whop",
"wordpress",
"fiverr",
"homestars",
"web_page"
]
},
"tags": {
"type": "array",
"maxItems": 100,
"items": {
"type": "string",
"minLength": 1,
"description": "Nonempty tag name."
}
},
"media": {
"type": "array",
"maxItems": 100,
"items": {
"type": "object",
"properties": {
"alt": {
"type": "string",
"minLength": 1,
"description": ""
},
"url": {
"type": "string",
"minLength": 1,
"description": "",
"format": "uri"
},
"type": {
"type": "string",
"enum": [
"image",
"video"
]
}
},
"required": [
"url",
"type"
],
"additionalProperties": false
}
},
"account": {
"type": "string",
"description": "Exact configured private account profile label; not a tenant or provider account ID."
},
"confirm": {
"type": "boolean",
"description": "Must be true for the requested mutation or exclusive private output file."
},
"payload": {
"type": "object",
"properties": {
"title": {
"type": "string",
"minLength": 1,
"description": ""
},
"text": {
"type": "string",
"minLength": 1,
"description": ""
},
"customer_name": {
"type": "string",
"minLength": 1,
"description": ""
},
"customer_company": {
"type": "string",
"minLength": 1,
"description": ""
},
"customer_tagline": {
"type": "string",
"minLength": 1,
"description": ""
},
"customer_username": {
"type": "string",
"minLength": 1,
"description": ""
},
"form_id": {
"type": "string",
"minLength": 1,
"description": ""
},
"url": {
"type": "string",
"minLength": 1,
"description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
"format": "uri"
},
"thumbnail_url": {
"type": "string",
"minLength": 1,
"description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
"format": "uri"
},
"customer_avatar": {
"type": "string",
"minLength": 1,
"description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
"format": "uri"
},
"customer_company_logo": {
"type": "string",
"minLength": 1,
"description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
"format": "uri"
},
"customer_url": {
"type": "string",
"minLength": 1,
"description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
"format": "uri"
},
"video_url": {
"type": "string",
"minLength": 1,
"description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
"format": "uri"
},
"type": {
"type": "string",
"enum": [
"text",
"video"
]
},
"customer_email": {
"type": "string",
"minLength": 1,
"description": "",
"format": "email"
},
"rating": {
"type": "integer",
"minimum": 1,
"maximum": 5
},
"date": {
"type": "string",
"minLength": 1,
"description": "",
"format": "date-time"
},
"approved": {
"type": "boolean",
"description": "Explicitly true publishes the testimonial; false keeps it pending."
},
"integration": {
"type": "string",
"enum": [
"twitter",
"product_hunt",
"google",
"facebook",
"reddit",
"capterra",
"g2",
"linkedin",
"app_store",
"trustpilot",
"shopify",
"play_store",
"yelp",
"slack",
"discord",
"apple_podcasts",
"telegram",
"whatsapp",
"instagram",
"youtube",
"tiktok",
"appsumo",
"amazon",
"zillow",
"udemy",
"chrome_web_store",
"airbnb",
"skillshare",
"realtor",
"sourceforge",
"whop",
"wordpress",
"fiverr",
"homestars",
"web_page"
]
},
"tags": {
"type": "array",
"maxItems": 100,
"items": {
"type": "string",
"minLength": 1,
"description": "Nonempty tag name."
}
},
"media": {
"type": "array",
"maxItems": 100,
"items": {
"type": "object",
"properties": {
"alt": {
"type": "string",
"minLength": 1,
"description": ""
},
"url": {
"type": "string",
"minLength": 1,
"description": "",
"format": "uri"
},
"type": {
"type": "string",
"enum": [
"image",
"video"
]
}
},
"required": [
"url",
"type"
],
"additionalProperties": false
}
}
},
"required": [
"type",
"customer_name"
],
"additionalProperties": false,
"description": "Complete native JSON body; do not mix with body flags or payload_file. Arrays use repeated JSON object flags or a whole native array in a private file."
},
"payload_file": {
"type": "string",
"minLength": 1,
"description": "Absolute regular non-symlink JSON body file, at most 1 MiB. Cannot mix with payload/body flags."
}
},
"required": [],
"additionalProperties": false
}
Native request: POST /testimonials. Provide native body fields OR payload OR payload_file, never mixed. Native body required: type, customer_name
json{
"name": "create_testimonial",
"method": "POST",
"path": "/testimonials",
"title": "Import a testimonial",
"description": "Create one text/video testimonial from an authorized existing customer statement. Explicit approval is required.",
"group": "testimonials",
"risk": "destructive",
"params": [],
"bodySchema": {
"type": "object",
"properties": {
"title": {
"type": "string",
"minLength": 1,
"description": ""
},
"text": {
"type": "string",
"minLength": 1,
"description": ""
},
"customer_name": {
"type": "string",
"minLength": 1,
"description": ""
},
"customer_company": {
"type": "string",
"minLength": 1,
"description": ""
},
"customer_tagline": {
"type": "string",
"minLength": 1,
"description": ""
},
"customer_username": {
"type": "string",
"minLength": 1,
"description": ""
},
"form_id": {
"type": "string",
"minLength": 1,
"description": ""
},
"url": {
"type": "string",
"minLength": 1,
"description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
"format": "uri"
},
"thumbnail_url": {
"type": "string",
"minLength": 1,
"description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
"format": "uri"
},
"customer_avatar": {
"type": "string",
"minLength": 1,
"description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
"format": "uri"
},
"customer_company_logo": {
"type": "string",
"minLength": 1,
"description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
"format": "uri"
},
"customer_url": {
"type": "string",
"minLength": 1,
"description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
"format": "uri"
},
"video_url": {
"type": "string",
"minLength": 1,
"description": "HTTPS URL without embedded credentials; provider retrieves media where supported.",
"format": "uri"
},
"type": {
"type": "string",
"enum": [
"text",
"video"
]
},
"customer_email": {
"type": "string",
"minLength": 1,
"description": "",
"format": "email"
},
"rating": {
"type": "integer",
"minimum": 1,
"maximum": 5
},
"date": {
"type": "string",
"minLength": 1,
"description": "",
"format": "date-time"
},
"approved": {
"type": "boolean",
"description": "Explicitly true publishes the testimonial; false keeps it pending."
},
"integration": {
"type": "string",
"enum": [
"twitter",
"product_hunt",
"google",
"facebook",
"reddit",
"capterra",
"g2",
"linkedin",
"app_store",
"trustpilot",
"shopify",
"play_store",
"yelp",
"slack",
"discord",
"apple_podcasts",
"telegram",
"whatsapp",
"instagram",
"youtube",
"tiktok",
"appsumo",
"amazon",
"zillow",
"udemy",
"chrome_web_store",
"airbnb",
"skillshare",
"realtor",
"sourceforge",
"whop",
"wordpress",
"fiverr",
"homestars",
"web_page"
]
},
"tags": {
"type": "array",
"maxItems": 100,
"items": {
"type": "string",
"minLength": 1,
"description": "Nonempty tag name."
}
},
"media": {
"type": "array",
"maxItems": 100,
"items": {
"type": "object",
"properties": {
"alt": {
"type": "string",
"minLength": 1,
"description": ""
},
"url": {
"type": "string",
"minLength": 1,
"description": "",
"format": "uri"
},
"type": {
"type": "string",
"enum": [
"image",
"video"
]
}
},
"required": [
"url",
"type"
],
"additionalProperties": false
}
}
},
"required": [
"type",
"customer_name"
],
"additionalProperties": false
},
"bodyRequired": true,
"privateOutput": false
}
update_testimonial
Change only native approval status and tag additions/removals. Text, rating and customer edits remain dashboard-only.
testimonial_id- Type
- string
- Required
- Required
- Meaning and constraints
- Exact testimonial ID. No slash, traversal or arbitrary URL.
approved- Type
- boolean
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
add_tags- Type
- array
- Required
- Optional
- Meaning and constraints
- {"maxItems": 100}
remove_tags- Type
- array
- Required
- Optional
- Meaning and constraints
- {"maxItems": 100}
account- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact configured private account profile label; not a tenant or provider account ID.
confirm- Type
- boolean
- Required
- Optional
- Meaning and constraints
- Must be true for the requested mutation or exclusive private output file.
payload- Type
- object
- Required
- Optional
- Meaning and constraints
- Complete native JSON body; do not mix with body flags or payload_file. Arrays use repeated JSON object flags or a whole native array in a private file.
payload.approved- Type
- boolean
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
payload.add_tags- Type
- array
- Required
- Optional
- Meaning and constraints
- {"maxItems": 100}
payload.remove_tags- Type
- array
- Required
- Optional
- Meaning and constraints
- {"maxItems": 100}
payload_file- Type
- string
- Required
- Optional
- Meaning and constraints
- Absolute regular non-symlink JSON body file, at most 1 MiB. Cannot mix with payload/body flags.
bashsenja-cli update-testimonial --help
senja-cli schema update-testimonial
json{
"type": "object",
"properties": {
"testimonial_id": {
"type": "string",
"minLength": 1,
"description": "Exact testimonial ID. No slash, traversal or arbitrary URL."
},
"approved": {
"type": "boolean"
},
"add_tags": {
"type": "array",
"maxItems": 100,
"items": {
"type": "string",
"minLength": 1,
"description": "Nonempty tag name."
}
},
"remove_tags": {
"type": "array",
"maxItems": 100,
"items": {
"type": "string",
"minLength": 1,
"description": "Nonempty tag name."
}
},
"account": {
"type": "string",
"description": "Exact configured private account profile label; not a tenant or provider account ID."
},
"confirm": {
"type": "boolean",
"description": "Must be true for the requested mutation or exclusive private output file."
},
"payload": {
"type": "object",
"properties": {
"approved": {
"type": "boolean"
},
"add_tags": {
"type": "array",
"maxItems": 100,
"items": {
"type": "string",
"minLength": 1,
"description": "Nonempty tag name."
}
},
"remove_tags": {
"type": "array",
"maxItems": 100,
"items": {
"type": "string",
"minLength": 1,
"description": "Nonempty tag name."
}
}
},
"required": [],
"additionalProperties": false,
"description": "Complete native JSON body; do not mix with body flags or payload_file. Arrays use repeated JSON object flags or a whole native array in a private file."
},
"payload_file": {
"type": "string",
"minLength": 1,
"description": "Absolute regular non-symlink JSON body file, at most 1 MiB. Cannot mix with payload/body flags."
}
},
"required": [
"testimonial_id"
],
"additionalProperties": false
}
Native request: PATCH /testimonials/{testimonial_id}. Provide native body fields OR payload OR payload_file, never mixed. Native body requires at least one approval or nonempty tag change.
json{
"name": "update_testimonial",
"method": "PATCH",
"path": "/testimonials/{testimonial_id}",
"title": "Update approval or tags",
"description": "Change only native approval status and tag additions/removals. Text, rating and customer edits remain dashboard-only.",
"group": "testimonials",
"risk": "destructive",
"params": [
{
"name": "testimonial_id",
"key": "testimonial_id",
"schema": {
"type": "string",
"minLength": 1,
"description": "Exact testimonial ID. No slash, traversal or arbitrary URL."
},
"in": "path",
"required": true,
"style": "form",
"explode": true
}
],
"bodySchema": {
"type": "object",
"properties": {
"approved": {
"type": "boolean"
},
"add_tags": {
"type": "array",
"maxItems": 100,
"items": {
"type": "string",
"minLength": 1,
"description": "Nonempty tag name."
}
},
"remove_tags": {
"type": "array",
"maxItems": 100,
"items": {
"type": "string",
"minLength": 1,
"description": "Nonempty tag name."
}
}
},
"required": [],
"additionalProperties": false
},
"bodyRequired": true,
"privateOutput": false
}
delete_testimonial
Permanently delete exactly the requested testimonial. Irreversible; confirmation required.
testimonial_id- Type
- string
- Required
- Required
- Meaning and constraints
- Exact testimonial ID. No slash, traversal or arbitrary URL.
account- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact configured private account profile label; not a tenant or provider account ID.
confirm- Type
- boolean
- Required
- Optional
- Meaning and constraints
- Must be true for the requested mutation or exclusive private output file.
bashsenja-cli delete-testimonial --help
senja-cli schema delete-testimonial
json{
"type": "object",
"properties": {
"testimonial_id": {
"type": "string",
"minLength": 1,
"description": "Exact testimonial ID. No slash, traversal or arbitrary URL."
},
"account": {
"type": "string",
"description": "Exact configured private account profile label; not a tenant or provider account ID."
},
"confirm": {
"type": "boolean",
"description": "Must be true for the requested mutation or exclusive private output file."
}
},
"required": [
"testimonial_id"
],
"additionalProperties": false
}
Native request: DELETE /testimonials/{testimonial_id}. No native JSON body.
json{
"name": "delete_testimonial",
"method": "DELETE",
"path": "/testimonials/{testimonial_id}",
"title": "Delete one testimonial",
"description": "Permanently delete exactly the requested testimonial. Irreversible; confirmation required.",
"group": "testimonials",
"risk": "destructive",
"params": [
{
"name": "testimonial_id",
"key": "testimonial_id",
"schema": {
"type": "string",
"minLength": 1,
"description": "Exact testimonial ID. No slash, traversal or arbitrary URL."
},
"in": "path",
"required": true,
"style": "form",
"explode": true
}
],
"bodySchema": null,
"bodyRequired": false,
"privateOutput": false
}
list_links
Read native form, widget, Wall of Love, quick-link, case-study and sizzle-reel groups with their IDs and URLs.
account- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact configured private account profile label; not a tenant or provider account ID.
bashsenja-cli list-links --help
senja-cli schema list-links
json{
"type": "object",
"properties": {
"account": {
"type": "string",
"description": "Exact configured private account profile label; not a tenant or provider account ID."
}
},
"required": [],
"additionalProperties": false
}
Native request: GET /links. No native JSON body.
json{
"name": "list_links",
"method": "GET",
"path": "/links",
"title": "Read project links",
"description": "Read native form, widget, Wall of Love, quick-link, case-study and sizzle-reel groups with their IDs and URLs.",
"group": "project_links",
"risk": "read",
"params": [],
"bodySchema": null,
"bodyRequired": false,
"privateOutput": false
}
send_invites
Send email invites using a selected form and its existing follow-up sequence. Local cap100 recipients, not a documented provider quota.
form_id- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact forms[].id from list_links.
recipients- Type
- array
- Required
- Optional
- Meaning and constraints
- {"minItems": 1, "maxItems": 100}
recipients[].email- Type
- string
- Required
- Required
- Meaning and constraints
- {"format": "email"}
recipients[].name- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
account- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact configured private account profile label; not a tenant or provider account ID.
confirm- Type
- boolean
- Required
- Optional
- Meaning and constraints
- Must be true for the requested mutation or exclusive private output file.
payload- Type
- object
- Required
- Optional
- Meaning and constraints
- Complete native JSON body; do not mix with body flags or payload_file. Arrays use repeated JSON object flags or a whole native array in a private file.
payload.form_id- Type
- string
- Required
- Required
- Meaning and constraints
- Exact forms[].id from list_links.
payload.recipients- Type
- array
- Required
- Required
- Meaning and constraints
- {"minItems": 1, "maxItems": 100}
payload.recipients[].email- Type
- string
- Required
- Required
- Meaning and constraints
- {"format": "email"}
payload.recipients[].name- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
payload_file- Type
- string
- Required
- Optional
- Meaning and constraints
- Absolute regular non-symlink JSON body file, at most 1 MiB. Cannot mix with payload/body flags.
bashsenja-cli send-invites --help
senja-cli schema send-invites
json{
"type": "object",
"properties": {
"form_id": {
"type": "string",
"minLength": 1,
"description": "Exact forms[].id from list_links."
},
"recipients": {
"type": "array",
"minItems": 1,
"maxItems": 100,
"items": {
"type": "object",
"properties": {
"email": {
"type": "string",
"minLength": 1,
"description": "",
"format": "email"
},
"name": {
"type": "string",
"minLength": 1,
"description": ""
}
},
"required": [
"email"
],
"additionalProperties": false
}
},
"account": {
"type": "string",
"description": "Exact configured private account profile label; not a tenant or provider account ID."
},
"confirm": {
"type": "boolean",
"description": "Must be true for the requested mutation or exclusive private output file."
},
"payload": {
"type": "object",
"properties": {
"form_id": {
"type": "string",
"minLength": 1,
"description": "Exact forms[].id from list_links."
},
"recipients": {
"type": "array",
"minItems": 1,
"maxItems": 100,
"items": {
"type": "object",
"properties": {
"email": {
"type": "string",
"minLength": 1,
"description": "",
"format": "email"
},
"name": {
"type": "string",
"minLength": 1,
"description": ""
}
},
"required": [
"email"
],
"additionalProperties": false
}
}
},
"required": [
"form_id",
"recipients"
],
"additionalProperties": false,
"description": "Complete native JSON body; do not mix with body flags or payload_file. Arrays use repeated JSON object flags or a whole native array in a private file."
},
"payload_file": {
"type": "string",
"minLength": 1,
"description": "Absolute regular non-symlink JSON body file, at most 1 MiB. Cannot mix with payload/body flags."
}
},
"required": [],
"additionalProperties": false
}
Native request: POST /invites. Provide native body fields OR payload OR payload_file, never mixed. Native body required: form_id, recipients
json{
"name": "send_invites",
"method": "POST",
"path": "/invites",
"title": "Send form invites",
"description": "Send email invites using a selected form and its existing follow-up sequence. Local cap100 recipients, not a documented provider quota.",
"group": "invites",
"risk": "destructive",
"params": [],
"bodySchema": {
"type": "object",
"properties": {
"form_id": {
"type": "string",
"minLength": 1,
"description": "Exact forms[].id from list_links."
},
"recipients": {
"type": "array",
"minItems": 1,
"maxItems": 100,
"items": {
"type": "object",
"properties": {
"email": {
"type": "string",
"minLength": 1,
"description": "",
"format": "email"
},
"name": {
"type": "string",
"minLength": 1,
"description": ""
}
},
"required": [
"email"
],
"additionalProperties": false
}
}
},
"required": [
"form_id",
"recipients"
],
"additionalProperties": false
},
"bodyRequired": true,
"privateOutput": false
}
list_accounts
Local profile labels/default/auth method only. No keys, token paths, provider identity or network request.
bashsenja-cli list-accounts --help
senja-cli schema list-accounts
json{
"type": "object",
"properties": {},
"required": [],
"additionalProperties": false
}
get_operation_schema
Local reviewed method/path/query/body schema and provenance for one native tool. No credentials or provider request.
operation- Type
- string
- Required
- Required
- Meaning and constraints
- Exact native tool name, e.g. update_testimonial or send_invites. {"enum": ["list_testimonials", "get_testimonial", "create_testimonial", "update_testimonial", "delete_testimonial", "list_links", "send_invites"]}
bashsenja-cli get-operation-schema --help
senja-cli schema get-operation-schema
json{
"type": "object",
"properties": {
"operation": {
"type": "string",
"enum": [
"list_testimonials",
"get_testimonial",
"create_testimonial",
"update_testimonial",
"delete_testimonial",
"list_links",
"send_invites"
],
"description": "Exact native tool name, e.g. update_testimonial or send_invites."
}
},
"required": [
"operation"
],
"additionalProperties": false
}
preview_testimonial_batch
Local validation and SHA-256 of exact ordered testimonial/import/invite work, selected profile label and reviewed schema. No provider reads, key load, identity check, price or rollback guarantee.
tasks- Type
- array
- Required
- Required
- Meaning and constraints
- One to twenty exact ordered supported testimonial/import/invite operations. Invite requests may include up to100 recipients each; review the exact complete recipient list and existing form follow-up sequence. {"minItems": 1, "maxItems": 20}
tasks[].tool- Type
- string
- Required
- Required
- Meaning and constraints
- {"enum": ["create_testimonial", "update_testimonial", "delete_testimonial", "send_invites"]}
tasks[].arguments- Type
- object
- Required
- Required
- Meaning and constraints
- Actual native tool arguments without account, confirm, payload_file or output_file.
account- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact selected private account profile; binds label, not key ownership.
bashsenja-cli preview-testimonial-batch --help
senja-cli schema preview-testimonial-batch
json{
"type": "object",
"properties": {
"tasks": {
"type": "array",
"minItems": 1,
"maxItems": 20,
"description": "One to twenty exact ordered supported testimonial/import/invite operations. Invite requests may include up to100 recipients each; review the exact complete recipient list and existing form follow-up sequence.",
"items": {
"type": "object",
"properties": {
"tool": {
"type": "string",
"enum": [
"create_testimonial",
"update_testimonial",
"delete_testimonial",
"send_invites"
]
},
"arguments": {
"type": "object",
"description": "Actual native tool arguments without account, confirm, payload_file or output_file."
}
},
"required": [
"tool",
"arguments"
],
"additionalProperties": false
}
},
"account": {
"type": "string",
"description": "Exact selected private account profile; binds label, not key ownership."
}
},
"required": [
"tasks"
],
"additionalProperties": false
}
submit_testimonial_batch
Confirmed one-to-twenty ordered testimonial/import/invite tasks. Prevalidate all and verify exact hash before first request. Stop on first failure with known results/failed index/unattempted indices; no retries, rollback or implicit continuation.
tasks- Type
- array
- Required
- Required
- Meaning and constraints
- One to twenty exact ordered supported testimonial/import/invite operations. Invite requests may include up to100 recipients each; review the exact complete recipient list and existing form follow-up sequence. {"minItems": 1, "maxItems": 20}
tasks[].tool- Type
- string
- Required
- Required
- Meaning and constraints
- {"enum": ["create_testimonial", "update_testimonial", "delete_testimonial", "send_invites"]}
tasks[].arguments- Type
- object
- Required
- Required
- Meaning and constraints
- Actual native tool arguments without account, confirm, payload_file or output_file.
account- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact selected private account profile; binds label, not key ownership.
confirm- Type
- boolean
- Required
- Optional
- Meaning and constraints
- Explicit approval for this exact requested ordered batch.
review_sha256- Type
- string
- Required
- Required
- Meaning and constraints
- Exact preview_testimonial_batch hash for identical requests, profile label, schema and order. {"pattern": "^[a-f0-9]{64}$"}
bashsenja-cli submit-testimonial-batch --help
senja-cli schema submit-testimonial-batch
json{
"type": "object",
"properties": {
"tasks": {
"type": "array",
"minItems": 1,
"maxItems": 20,
"description": "One to twenty exact ordered supported testimonial/import/invite operations. Invite requests may include up to100 recipients each; review the exact complete recipient list and existing form follow-up sequence.",
"items": {
"type": "object",
"properties": {
"tool": {
"type": "string",
"enum": [
"create_testimonial",
"update_testimonial",
"delete_testimonial",
"send_invites"
]
},
"arguments": {
"type": "object",
"description": "Actual native tool arguments without account, confirm, payload_file or output_file."
}
},
"required": [
"tool",
"arguments"
],
"additionalProperties": false
}
},
"account": {
"type": "string",
"description": "Exact selected private account profile; binds label, not key ownership."
},
"confirm": {
"type": "boolean",
"description": "Explicit approval for this exact requested ordered batch."
},
"review_sha256": {
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "Exact preview_testimonial_batch hash for identical requests, profile label, schema and order."
}
},
"required": [
"tasks",
"review_sha256"
],
"additionalProperties": false
}
export_testimonials
Confirmed paginated GET export to an exclusive new0600 JSON file. Stop on short native page or local caps. Never downloads media, follows URLs, overwrites files, retries or implies an atomic complete backup.
sort- Type
- string
- Required
- Optional
- Meaning and constraints
- Native sort field; direction uses order. {"enum": ["date", "rating"]}
order- Type
- string
- Required
- Optional
- Meaning and constraints
- {"enum": ["asc", "desc"]}
approved- Type
- boolean
- Required
- Optional
- Meaning and constraints
- Exact native/schema value
rating- Type
- integer
- Required
- Optional
- Meaning and constraints
- {"minimum": 1, "maximum": 5}
type- Type
- string
- Required
- Optional
- Meaning and constraints
- {"enum": ["text", "video"]}
integration- Type
- string
- Required
- Optional
- Meaning and constraints
- {"enum": ["twitter", "product_hunt", "google", "facebook", "reddit", "capterra", "g2", "linkedin", "app_store", "trustpilot", "shopify", "play_store", "yelp", "slack", "discord", "apple_podcasts", "telegram", "whatsapp", "instagram", "youtube", "tiktok", "appsumo", "amazon", "zillow", "udemy", "chrome_web_store", "airbnb", "skillshare", "realtor", "sourceforge", "whop", "wordpress", "fiverr", "homestars", "web_page"]}
tags- Type
- array
- Required
- Optional
- Meaning and constraints
- {"maxItems": 100}
query- Type
- string
- Required
- Optional
- Meaning and constraints
- Native full-text search, including customer name/email; output may contain personal data.
lang- Type
- string
- Required
- Optional
- Meaning and constraints
- Native ISO 639 language selector.
limit- Type
- integer
- Required
- Optional
- Meaning and constraints
- Native page size. total counts only the current page. {"minimum": 1, "maximum": 1000}
page- Type
- integer
- Required
- Optional
- Meaning and constraints
- {"minimum": 1}
account- Type
- string
- Required
- Optional
- Meaning and constraints
- Exact configured private account profile label; not a tenant or provider account ID.
confirm- Type
- boolean
- Required
- Optional
- Meaning and constraints
- Explicit approval for this exact requested ordered batch.
start_offset- Type
- integer
- Required
- Optional
- Meaning and constraints
- Resume inside the first requested page using an export receipt offset and identical filters/page size. Provider state may have changed. {"minimum": 0, "maximum": 999}
max_pages- Type
- integer
- Required
- Optional
- Meaning and constraints
- Local request budget, default10. {"minimum": 1, "maximum": 100}
max_items- Type
- integer
- Required
- Optional
- Meaning and constraints
- Local item budget, default1000. May stop within a page; receipt records an offset. {"minimum": 1, "maximum": 10000}
output_file- Type
- string
- Required
- Required
- Meaning and constraints
- Absolute new file in an existing private directory. Restrict Windows ACLs separately.
bashsenja-cli export-testimonials --help
senja-cli schema export-testimonials
json{
"type": "object",
"properties": {
"sort": {
"type": "string",
"enum": [
"date",
"rating"
],
"description": "Native sort field; direction uses order."
},
"order": {
"type": "string",
"enum": [
"asc",
"desc"
]
},
"approved": {
"type": "boolean"
},
"rating": {
"type": "integer",
"minimum": 1,
"maximum": 5
},
"type": {
"type": "string",
"enum": [
"text",
"video"
]
},
"integration": {
"type": "string",
"enum": [
"twitter",
"product_hunt",
"google",
"facebook",
"reddit",
"capterra",
"g2",
"linkedin",
"app_store",
"trustpilot",
"shopify",
"play_store",
"yelp",
"slack",
"discord",
"apple_podcasts",
"telegram",
"whatsapp",
"instagram",
"youtube",
"tiktok",
"appsumo",
"amazon",
"zillow",
"udemy",
"chrome_web_store",
"airbnb",
"skillshare",
"realtor",
"sourceforge",
"whop",
"wordpress",
"fiverr",
"homestars",
"web_page"
]
},
"tags": {
"type": "array",
"maxItems": 100,
"items": {
"type": "string",
"minLength": 1,
"description": "Nonempty tag name."
}
},
"query": {
"type": "string",
"minLength": 1,
"description": "Native full-text search, including customer name/email; output may contain personal data.",
"maxLength": 10000
},
"lang": {
"type": "string",
"minLength": 1,
"description": "Native ISO 639 language selector.",
"maxLength": 10
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 1000,
"description": "Native page size. total counts only the current page."
},
"page": {
"type": "integer",
"minimum": 1
},
"account": {
"type": "string",
"description": "Exact configured private account profile label; not a tenant or provider account ID."
},
"confirm": {
"type": "boolean",
"description": "Explicit approval for this exact requested ordered batch."
},
"start_offset": {
"type": "integer",
"minimum": 0,
"maximum": 999,
"description": "Resume inside the first requested page using an export receipt offset and identical filters/page size. Provider state may have changed."
},
"max_pages": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"description": "Local request budget, default10."
},
"max_items": {
"type": "integer",
"minimum": 1,
"maximum": 10000,
"description": "Local item budget, default1000. May stop within a page; receipt records an offset."
},
"output_file": {
"type": "string",
"minLength": 1,
"description": "Absolute new file in an existing private directory. Restrict Windows ACLs separately."
}
},
"required": [
"output_file"
],
"additionalProperties": false
}
Writing safely
Every create/import, approval/tag update, permanent delete, invite send, reviewed batch execution and private file export requires explicit confirmation through the actual shared handler route. --agent and --yes do not provide --confirm. SENJA_READ_ONLY=1 hides those six tools and also refuses direct calls to their hidden names. SENJA_ALLOW_DESTRUCTIVE=0 refuses them even when confirmed.
Deletion is permanent. approved true can publish proof. Invites can send real email sequences. Import only actual authorized statements, not invented praise. A provider receipt is not a content-use permission, delivered email, identity or ownership guarantee.
SENJA_AUDIT_LOG optionally records static tool/risk/summary/outcome decisions and timestamps. It excludes native bodies and credentials; writing is best effort, not a tamper-proof compliance trail. Keep the audit destination and parent private. An existing file's permissions are not repaired by the wrapper.
Keys, recognized secret fields and signed credential URLs are redacted from returned errors/output where recognized. Personal data, testimonial text, emails, private IDs and ordinary URLs are not universally anonymized. Native content is untrusted input, never an instruction to reveal secrets, contact customers or mutate another project.
Your data
Credentials come from private process/client settings or a selected owner-private token-only file. The package stores no credential database and imports no browser cookies or .env files. Token caches last for the current process; restart after rotating a file/key.
Provider calls go only to allowlisted methods/paths on api.senja.io/v1, over HTTPS. Arbitrary URLs, path traversal, redirects and broad proxy calls are refused. Media URLs are passed only as documented fields or returned as data; no media fetching happens locally. Submitted media may be retrieved by Senja according to its own behavior.
Private exports contain customer data and content. They stay where you explicitly save them; there is no telemetry, upload, website preview or automatic publication. Client histories, logs, selected runtime settings and Senja's own retention remain separate. Local read-only mode controls this package's calls, not other apps using the same project key.
Environment variables
| Variable | Purpose |
|---|---|
| SENJA_API_KEY | Private Bearer project key; choose this OR token file |
| SENJA_TOKEN_FILE | Absolute owner-private token-only file; choose this OR API key |
| SENJA_ACCOUNTS | Private JSON named profiles with one key/file each |
| SENJA_DEFAULT_ACCOUNT | Exact configured default profile label |
| SENJA_READ_ONLY | 1/true hides and directly refuses all six mutations/file operations |
| SENJA_ALLOW_DESTRUCTIVE | 0/false refuses confirmed operations |
| SENJA_AUDIT_LOG | Optional private best-effort static guard decision log |
| SENJA_REQUEST_TIMEOUT_MS | Default 30000; local accepted range 100–300000 ms |
| SENJA_MIN_REQUEST_INTERVAL_MS | Default 250; local accepted range 0–10000 ms, not distributed native quota enforcement |
Official and community comparisons
Official hosted MCP
Senja already has official account MCP at https://mcp.senja.io. It searches testimonials, finds proof for a use case, creates testimonials, tags records, retrieves asset links/embeds and sends form invites. Current setup docs include Free, Starter and Pro. Hosted account authorization and client approvals are separate from this local API-key package.
Use the official connector when that native experience fits your task. A dedicated official task CLI was not identified in the provider material reviewed on October 3, 2026; this is not a universal or permanent absence claim. This package does not claim to add invites that the official MCP already supports, expose every Senja UI feature, create Studio graphics or replace native embed editing.
Reviewed community server
andrewconnell/senja-mcp at commit 417445647eac47f94c2d12d9196a68d2e1d22559 exposes three testimonial MCP tools. Its inspected API client already uses Bearer auth, separate sort/order, lang/limit and repeated tag query values. Its package does not declare a standalone task CLI; its create handler has no mandatory confirmation argument. This says nothing about external clients' approval controls.
The reviewed interface describes a data array and paid-plan prerequisite; current provider documentation describes testimonials and current-page total, and covers Free/Starter/Pro. Our request/response fixtures follow current provider fields. Community customer_website is not the current documented customer_url field.
Useful owned workflows and limits
The verified addition is a shared task CLI/local MCP with isolated named project profiles, mandatory mutation/file approval, direct read-only refusal, locally reviewed ordered writes and bounded private paginated export with explicit page/offset continuation. These controls are exercised in fixtures and real protocol/CLI processes. They do not establish overall superiority, authenticated account outcomes or token savings.
- This package
- 12 shared MCP tools and task CLI commands
- Existing alternatives
- Official hosted MCP and reviewed community stdio MCP
- This package
- Seven reviewed documented endpoints
- Existing alternatives
- Official hosted tools may cover different native features
- This package
- Unique local profiles, no global credential fallback
- Existing alternatives
- Official connector authorization stays native
- This package
- Exact local hash, prevalidation, stop on failure
- Existing alternatives
- Not a provider-state lock or replacement for client approval
- This package
- Bounded pages/items/bytes and exclusive JSON file
- Existing alternatives
- Not an atomic complete backup, consent registry or media downloader
- This package
- Actual matched Codex measurement pending
- Existing alternatives
- No percentage or zero-total-token claim
Versions and migration
| Component | Reviewed version |
|---|---|
| Package/desktop | 2.0.0 |
| Native public API | v1; seven endpoints checked 2026-10-03 |
| Community source | 417445647eac47f94c2d12d9196a68d2e1d22559 |
| Node | >=22 |
| Historical private MCP | 1.0.0; three tools |
| Matched Codex task/token usage | Pending |
- Current contract
- limit
- Required change
- Use native page-size field
- Current contract
- lang
- Required change
- Use native language selector
- Current contract
- sort date/rating plus order
- Required change
- Send field and direction separately
- Current contract
- tags array
- Required change
- Repeat --tags or use a JSON array
- Current contract
- customer_name/customer_email/customer_tagline/customer_company
- Required change
- Use native fields and required type
- Current contract
- customer_avatar/customer_company_logo
- Required change
- Use native HTTPS fields
- Current contract
- url is source; customer_url is customer website
- Required change
- Choose the actual intended field
- Current contract
- 12 tools with credential-free discovery and guarded effects
- Required change
- Discover tools before private setup; update scripts for approval
- Current contract
- senja-cli and senja-mcp
- Required change
- Use @thenavidm scope and @latest
version history records the dated major update. Private legacy history stays private; source publishing starts from a clean verified snapshot, preserving AGPL-3.0.
More tools for your proof workflow
Connect only the services your requested customer and publishing work needs.
Senja MCP Server & CLI FAQs
Official MCP comparison, private projects, current native arguments, approved effects, bounded exports and maintenance.
Yes.
Its hosted connector already searches testimonials, creates proof, retrieves asset links and sends form invites.
This package adds a shared terminal/local task interface and the documented local workflows.
Use the official option when it fits your needs; the comparison does not claim ours replaces its full native feature set.
The CLI runs the same discovered tools through the same in-memory MCP handlers, input validation and write guard.
Scripts can use JSON, field selection and exit codes.
A dedicated official task CLI was not identified in the reviewed provider material; that finding is dated, not a permanent absence claim.
Current provider REST and MCP setup documentation includes Free, Starter and Pro.
Account restrictions and native feature eligibility remain in Senja.
The package is free under AGPL-3.0 and cannot bypass a plan or permission check; do not reuse older community paid-only prerequisites as current facts.
Choose the intended project and open Automate in Senja.
Store exactly one key privately in SENJA_API_KEY or an absolute owner-private SENJA_TOKEN_FILE outside repositories.
The client uses Bearer authentication.
Never paste resolved secrets into README examples, public issues, screenshots or AI chats.
Yes.
SENJA_ACCOUNTS supplies unique private named profiles, each with its own key or token file.
Select an exact name with --account.
Named profiles never inherit global credentials or another project.
Labels are local settings and do not prove the provider key owner or project identity.
No. login prints private setup instructions and never makes a request, opens an OAuth flow, generates a key or imports a browser session. doctor without --network checks configuration only. doctor --network deliberately makes one limit=1 testimonial request and prints verification metadata.
The reviewed catalogue includes testimonial list/get/create/PATCH/delete, project links and form invites, plus five local/workflow helpers.
This is the current seven-endpoint public REST scope reviewed for this package, not a claim to expose every hosted MCP or Senja UI action.
Native PATCH supports only approval status and tag additions/removals.
Text, rating and customer edits belong in the Senja dashboard. create_testimonial uses actual customer_name/type fields for an authorized import; it does not invent a generalized edit API.
Yes, according to current native API documentation; false returns it to pending.
These are confirmed account changes.
Approval does not establish customer permission to reuse their words or media, and reading a testimonial never authorizes publishing it elsewhere.
Use native query for text/title/customer-field search, repeat --tags for tag names, and use rating/type/integration/approved/lang as appropriate. sort is date or rating and order is asc or desc.
The wrapper rejects stale per_page, language and combined date_desc-style sort arguments before network traffic.
No.
Native total counts the current returned page.
Export stops on a short native page or explicit local caps, recording page/offset/limit continuation.
It does not infer a project-wide count from total or promise a consistent snapshot while provider content changes.
Use export_testimonials with explicit confirmation and an absolute new private file.
Defaults are10pages and1000items; local maximums are100pages,10000items and5MiB JSON.
Resume to a different file using the recorded page/start_offset/limit and unchanged filters.
Combine/de-duplicate changing native IDs deliberately; no automatic append or atomic backup is promised.
No.
JSON includes native media URLs, transcripts and metadata where returned.
The package never follows these URLs or downloads video/image/audio files.
Signed credential URLs and known keys are redacted where recognized; other personal/customer content is still private data.
The selected form ID and its existing email/follow-up sequence determine native messages.
Use a real forms[].id from list_links and only explicitly approved recipients.
The local 100-recipient cap is not a native quota.
Native sent/skipped receipts do not prove inbox delivery or consent, and invites also exist in the official MCP.
It prevalidates every complete task and binds exact order/requests/profile label/schema to a local hash before sequential execution.
The hash is not a single-use provider token, human signature, provider-state lock, consent record or ownership proof.
Reconfirm changing provider state when your task requires it.
Execution stops at the first failure with knownResults, failedIndex and unattemptedIndices.
A failed write may already have taken effect and native follow-up emails can continue.
There is no retry, rollback or automatic continuation.
Inspect native state and receipts before explicitly requesting another action.
No.
SENJA_READ_ONLY=1 both hides the six confirmed tools and refuses direct hidden calls through the actual handlers.
It also refuses private file exports.
SENJA_ALLOW_DESTRUCTIVE=0 disables these effects even when confirmed; --agent and --yes never provide explicit --confirm.
Codex and compatible local stdio clients can register npx -y @thenavidm/senja-mcp-cli@latest.
INSTALL.md covers Claude Code/Desktop, Cursor, VS Code/Copilot, Windsurf, Zed, Gemini CLI, Docker and other stdio clients, plus Windows/macOS/Linux runtime notes.
Browser-only clients need a remote connector such as the official hosted MCP.
The .mcpb includes production dependencies and asks for private sensitive settings or a token file, but compatible hosts still need a Node 22 runtime and organization support.
Install newer bundle versions manually. npx@latest resolves the current registry version when the server is restarted; it does not replace a running process or provide guaranteed background updates.
Actual equivalent successful Codex task/token measurements are pending.
MCP loading modes, CLI schema/help discovery, outputs, skills and caching all affect costs.
No character-based estimate, universal superiority or zero-total-token claim is published.
Proven fixture behavior and actual public artifact checks are listed separately from authenticated outcomes and desktop GUI acceptance.
Navid.me is reader-supported. When you buy through links on this site, I may earn an affiliate commission. Learn more.
More MCP servers & CLIs
Related free tools
Free AI newsletterThe most actionable AI newsletter for founders
Every week, get proven AI strategies, curated tools, and step-by-step systems to grow your audience, create better content, and build a profitable creator business.
No fluff, no filler, no BS. Just five minutes each week that might level up your online business and life.
P.S. Sign up now to get free access to my ultimate AI tools guide for creators.













