Stacklink

Errors & idempotency

The error envelope, common codes, and safe retries.

The error envelope

Every API error returns one JSON shape:

{
  "success": false,
  "code": "api_key_scope_missing",
  "message": "API key is missing required scope: tools:execute",
  "details": {}
}

code is machine-readable and stable — branch on it, not on message. details carries optional structured context (e.g. rate-limit metadata).

Common codes

StatusCodeMeaning
400validation_error / invalid_jsonRequest failed schema validation.
401invalid_registration_key (and key-invalid variants)Missing or invalid credentials.
403api_key_scope_missingThe key lacks the required scope.
403mcp_origin_not_allowedBrowser origin not in the MCP allowlist.
404execution_not_found, request_log_not_found, …Resource doesn't exist (or isn't yours).
429rate-limit codesPlan rate limit exceeded — see Billing.
500internal_errorUnexpected server error.

Authentication uses Authorization: Bearer <key> or x-stacklink-key; registration/admin endpoints use x-stacklink-registration-key.

Retry guidance

  • Safe to retry: network failures, 429 (back off), 500.
  • Don't retry blindly: 400/401/403/404 — fix the request.
  • Mutations: always pass an idempotencyKey.

Idempotency

STACKLINK_EXECUTE_TOOL and STACKLINK_MULTI_EXECUTE_TOOL (and their REST/SDK forms) accept an idempotencyKey. Replaying the same key returns the original execution record — the provider call does not run twice:

await session.executeTool({
  toolKey: 'razorpay.payments.create_refund',
  input: { payment_id, amount },
  idempotencyKey: `refund-${orderId}`,
});

For agents, this is the difference between "the model retried" and "the customer was refunded twice." Pair it with execution control: on timeout, STACKLINK_WORKBENCH_EXECUTION with action: "wait" or a replay with the same key recovers the result safely.

Webhook-side retries

Outbound event deliveries have their own retry + dead-letter behavior — see Webhooks.

On this page