Skip to Content
API referencePOST /v1/actions

POST /v1/actions

The core action proxy. Every call your agent makes to a connected SaaS platform flows through this endpoint.

Most agents call this indirectly via the MCP use_platform tool. Direct invocation is only needed when building a custom MCP server or integrating from a non-MCP host.

Request

POST /v1/actions HTTP/1.1 Host: api.agentvalet.ai Authorization: Bearer <agent-rs256-jwt> Content-Type: application/json
{ "platform": "slack", "endpoint": "/api/chat.postMessage", "method": "POST", "scope": "slack:write", "data": { "channel": "#general", "text": "Hello" }, "headers": {} }
FieldTypeRequiredNotes
platformstringyesPlatform id from list_platforms (e.g. slack, gmail, stripe)
endpointstringyesThe SaaS endpoint path. Validated by the SSRF guard — no private/loopback addresses
methodstringyesGET / POST / PUT / PATCH / DELETE
scopestringyesThe scope the agent claims for this call. Must be granted in the dashboard permission matrix
dataobjectnoRequest payload forwarded to the SaaS
headersobjectnoExtra headers forwarded to the SaaS

Success — 200 OK

The upstream response wrapped in a discovery envelope:

{ "status": 200, "data": { "ok": true, "channel": "C123", "ts": "1715000000.000100" }, "_links": [ { "capability": "audit.query", "endpoint": "GET /v1/audit" }, { "capability": "agent.permissions", "endpoint": "GET /v1/agent/permissions" } ] }

If the org has PII redaction beta enabled and the agent has a per-platform visibility map, the data body is rewritten before the response is returned. The audit row records pii_detected, pii_categories, pii_redacted, and pii_record_count. See PII redaction.

Pending approval — 202 Accepted

When the scope is marked require_approval in the permission matrix:

{ "status": "pending_approval", "approval_id": "01HKZ7...", "message": "Owner approval required" }

Your agent should poll GET /v1/approvals/:id until status is approved (with result populated) or denied / expired. The MCP use_platform tool does this long-poll for you for up to 50 seconds; after that it returns the 202 envelope and your agent should explain the wait to the user.

Approvals expire 24 hours from creation. The owner can be notified via push (mobile), email (delegates), and the dashboard inbox.

Error codes

All errors follow the common envelope. The error identifier is stable.

StatuserrorCauseFix
400invalid_jwtJWT malformed or missing required claimCheck agent_id, owner_id, iat, exp claims
400secrets_in_paramsRequest body matched the secrets scanner (AWS key, Slack token, etc.)Don’t embed credentials in data; use the platform’s own auth mechanism
400endpoint_blockedSSRF guard rejected the endpoint (private/loopback)Use the platform’s public API endpoint
401Missing Bearer tokenNo Authorization: Bearer headerAdd the header
401Invalid JWTSignature verification failed against the agent’s public keyThe agent’s private key doesn’t match the registered public key — re-register or rotate
401Unknown agentagent_id claim doesn’t match any rowConfirm the agent exists in the dashboard and isn’t soft-deleted
402plan_inactiveOrg plan is past_due or cancelledUpdate billing
403Permission denied (with reason: scope_not_granted or similar)The scope isn’t in the agent’s permission matrixGrant the scope in Agents → permissions
403AuthZEN policy deniedA policy decision from the AuthZEN evaluator denied the callInspect the audit row’s metadata.authzen_reason
502Upstream request failed (with detail: "Response could not be safely returned")PII redaction failed closed — Presidio returned an error and the org has the beta flag onSee troubleshooting: PII fail-closed 502
502Upstream request failed (with the platform error in detail)The SaaS returned 5xx or the call timed outCheck the upstream platform status; the proxy retried per its policy

Audit

Every call writes one row to audit_log with:

  • action = the requested scope
  • result = allowed / denied / pending_approval / error
  • metadata.response_status from the upstream
  • pii_* columns if PII redaction ran
  • Forensic columns (ip_address, user_agent, geo_country, etc.) if your org has forensic capture enabled
Last updated on