Skip to main content

Approvals

Flow supports optional human review before delivery. When a gate is configured with approvalMode: "manual", validated runs are held for approver decision before proceeding.

Approval Modes

ModeBehavior
auto (default)Runs proceed directly after validation — no human review
manualRuns wait at pending_approval status until an approver approves or rejects

Configuring Approvers

Set up approval when creating or updating a gate:

{
"approvalMode": "manual",
"approvalConfig": {
"approvers": [
{ "type": "internal", "email": "manager@company.com" },
{ "type": "external", "email": "auditor@partner.com" }
],
"timeout_hours": 48
}
}

Approver Types

TypeDescription
internalA user with a Rynko account on your team — reviews via the dashboard
externalAny email address — reviews via a magic link sent by email

Decision Logic

Flow uses any-approves logic:

  • The first approval moves the run to approved and triggers delivery immediately
  • The first rejection moves the run to rejected (terminal) — no delivery

Once a decision is made, other approvers cannot override it.


Internal Approvers

Internal approvers review runs directly in the Rynko dashboard.

Dashboard Inbox

curl https://api.rynko.dev/api/flow/approvals \
-H "Authorization: Bearer YOUR_API_KEY"

Returns all pending approvals assigned to the authenticated user.

Making a Decision

# Approve
curl -X POST https://api.rynko.dev/api/flow/approvals/APPROVAL_ID/approve \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "comment": "Looks good, approved." }'

# Reject
curl -X POST https://api.rynko.dev/api/flow/approvals/APPROVAL_ID/reject \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "comment": "Amount exceeds policy limit." }'

The comment field is optional (max 1000 characters).


External approvers receive an email with a magic link that takes them to a review portal — no Rynko account required.

How It Works

  1. A run reaches pending_approval status
  2. Flow sends an email to each external approver with a unique magic link
  3. The approver clicks the link and enters their email as identity verification
  4. They receive a short-lived review token (valid for 2 hours)
  5. They can view the run details and approve or reject

Review Portal Endpoints

These endpoints are public (no API key required) — they use the magic link token for authentication.

Authenticate

curl -X POST https://api.rynko.dev/api/flow/review/authenticate \
-H "Content-Type: application/json" \
-d '{
"token": "MAGIC_LINK_TOKEN",
"email": "auditor@partner.com"
}'

Response:

{
"reviewToken": "eyJ...",
"expiresIn": 7200
}

The email must match the token's intended recipient (identity challenge).

View Inbox

curl https://api.rynko.dev/api/flow/review/inbox \
-H "Authorization: Bearer REVIEW_TOKEN"

View Approval Details

curl https://api.rynko.dev/api/flow/review/approvals/APPROVAL_ID \
-H "Authorization: Bearer REVIEW_TOKEN"

Returns the approval record with full run context (payload, validation results, gate info).

Approve or Reject

# Approve
curl -X POST https://api.rynko.dev/api/flow/review/approvals/APPROVAL_ID/approve \
-H "Authorization: Bearer REVIEW_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "comment": "Approved after review." }'

# Reject
curl -X POST https://api.rynko.dev/api/flow/review/approvals/APPROVAL_ID/reject \
-H "Authorization: Bearer REVIEW_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "comment": "Data does not match requirements." }'

If the approver didn't receive the email or the link expired:

curl -X POST https://api.rynko.dev/api/flow/review/resend \
-H "Content-Type: application/json" \
-d '{
"token": "ORIGINAL_MAGIC_LINK_TOKEN",
"email": "auditor@partner.com"
}'

Timeout

If no approver makes a decision within the configured timeout_hours, the approval expires. Configure the timeout (1-720 hours) in the gate's approvalConfig.


Delivery Configuration for Human-in-the-Loop Workflows

When using manual approval, consider how your application will receive the reviewer's decision.

Production Best Practice: Webhooks

For production human-in-the-loop workflows, configure a webhook delivery channel on the gate. This way, once an approver approves or rejects a run, Flow automatically delivers the result to your endpoint — no polling required.

{
"approvalMode": "manual",
"deliveryChannels": [
{
"type": "webhook",
"url": "https://your-app.com/webhooks/flow",
"secret": "whsec_..."
}
]
}

This eliminates the need to poll the API and reduces latency between the reviewer's decision and your application's reaction.

Without Delivery Channels

If no delivery channels are configured, the run will still move to approved or rejected status after the reviewer decides, but no outbound notification is sent. In this case, you must:

  • Poll the API: Call GET /api/flow/runs/:id periodically to check the run status
  • Use MCP tools: Use the get_run_status MCP tool from an AI agent to check the outcome

This approach works for prototyping and low-volume use cases but is not recommended for production — it adds latency and consumes unnecessary API calls.


Approval Limits by Plan

PlanMax Approvers per Gate
Free5
Starter10
Growth25
ScaleUnlimited