Integrations

API overview and request format

Call agaro through the authenticated version 1 action API, understand actor bound keys, request shapes, methods, responses, rate limits, and errors.

agaro exposes an authenticated action API under /api/v1. It dispatches the same registered server actions used by the application, so validation, module gates, model permissions, record scope, workspace mutation checks, and activity attribution remain in force.

API key access requires an active MCP seat for the bound actor. The API is not an unmetered alternative to the MCP entitlement.

Create an actor bound key

A workspace Super Admin opens Settings → Developer and AI → API and MCP Keys.

  1. Confirm the workspace is on Growth or Scale and the intended actor has an active MCP seat.
  2. Select Create an MCP key.
  3. Give the key a specific name, such as Revenue reporting integration.
  4. Bind it to an active Super Admin or Manager.
  5. Choose 30 days, 90 days, one year, or never expires.
  6. Copy the plaintext immediately.

Only the SHA 256 hash is stored. The full key cannot be retrieved after you close the reveal. Prefer an expiring key and rotate it on a schedule.

Authentication

Current keys encode their workspace route and are bound to one actor. Send the key as a bearer token:

http
Authorization: Bearer <your-key>

For a JSON body, also send:

http
Content-Type: application/json

Do not add an actor header to change identity. The actor stored on the key is authoritative, and request headers cannot rebind it.

Direct action route

Registered actions use this pattern:

text
POST https://erp.agaro.ai/api/v1/{module}/{action}

Examples of route shape include:

text
POST /api/v1/clients/list
POST /api/v1/leads/create
POST /api/v1/invoices/recordPayment
POST /api/v1/tasks/complete

Action names and schemas evolve with the product. Use the current registered action surface rather than copying an old list into an integration.

Request bodies

The canonical body wraps positional action arguments in args:

json
{
  "args": [
    {
      "companyName": "Example Company"
    }
  ]
}

For a one argument action, the raw input object is also accepted:

json
{
  "companyName": "Example Company"
}

An action with no arguments can receive an empty body or:

json
{ "args": [] }

Use args for generated clients because it remains unambiguous when an action takes more than one argument.

Example request

bash
curl -X POST \
  "https://erp.agaro.ai/api/v1/clients/list" \
  -H "Authorization: Bearer <your-key>" \
  -H "Content-Type: application/json" \
  --data '{"args":[]}'

Never place the key in a URL, source repository, browser bundle, analytics event, or shared command history.

GET and mutation methods

Read actions can be called with GET where the route resolves them as nonmutating. GET accepts an encoded args query parameter or maps query parameters to a single object for supported actions.

Mutating actions cannot be called with GET. Use POST, PATCH, PUT, or DELETE as supported by the route. Sending a body through POST, PATCH, or PUT requires application/json; otherwise the API returns 415 Unsupported Media Type.

Inventory additionally supports namespaced routes such as:

text
/api/v1/inventory/{entity}/{action}

Some inventory entities also support collection and item conventions for list, create, get, update, and archive or remove.

Response shape

Actions generally return the same structured result used by the application. A successful action can look like:

json
{
  "ok": true,
  "data": {}
}

Validation or business failures that return ok: false use HTTP 400 and can include fieldErrors and formError. Dates use their normal JSON representation. Big integer money values are serialized as exact decimal strings rather than losing precision.

Status codes

StatusMeaning
400Invalid JSON, validation failure, or an action returned ok: false
401Missing bearer credential
402The actor lacks an active MCP seat or the workspace billing state blocks MCP
403Invalid, expired, revoked, or unauthorized key, actor, module, or record action
404Unknown route or deliberately unavailable internal action
405A mutating action was attempted with GET or HEAD was used
415A body was sent without JSON content type
429Key, actor, source, or workspace rate limit was reached
500Unexpected server failure

Use the returned status and error body. Do not retry a validation or permission failure as if it were a transient network error.

Rate limits and idempotency

The API limits requests per actor and per workspace. A 429 response includes a 60 second retry hint. Apply bounded exponential backoff and avoid parallel retry storms.

Not every action is idempotent. Retrying a create action can create another business record unless that action has its own deduplication key. For payments, billing, sends, imports, and other high impact writes, keep the provider or action idempotency identifier and check the result before retrying.

Rotate and revoke

Rotate a key from the key table to issue a new plaintext for the same key record. Rotation invalidates the previous secret immediately. Update the client before its next call.

Revoke a key when the integration is retired or the secret may have been exposed. Revocation is immediate and cannot be undone. Create a new key instead of trying to recover a revoked one.

The key table shows prefix, bound actor, last used time, call count, expiry, rotation, and revocation state.

Troubleshooting

A new key returns 402

Confirm the bound actor still has an active MCP seat and the workspace is on an eligible active plan. The seat belongs to the actor, not to the key name.

A request returns 403 after a role change

Keys use live actor and creator authority. A suspended, removed, deleted, or demoted actor can lose access immediately. A key also cannot act above its creator's current privilege ceiling.

POST returns 415

Send Content-Type: application/json whenever the request contains a body.

An action is not found

Internal jobs and provider callback actions are deliberately excluded. Confirm the current registered module and action names and use the supported public integration path.