Skip to main content

Get Action Status

Poll for the current status of an action. This endpoint is optimized for SDK clients to efficiently poll for approval decisions.

Endpoint

GET /api/v1/actions/{action_id}/status

Authentication

This endpoint supports both authentication methods:

  • API Key: X-API-Key header (recommended for SDKs)
  • JWT Token: Authorization: Bearer <token> header

Request

Headers

HeaderRequiredDescription
X-API-KeyYes*Your API key
AuthorizationYes*Bearer token (alternative to X-API-Key)

*One of X-API-Key or Authorization is required.

Path Parameters

ParameterTypeRequiredDescription
action_idintegerYesThe unique action identifier

Response

Success (200 OK)

{
"action_id": 12345,
"status": "approved",
"risk_score": 35.0,
"timestamp": "2026-01-20T14:30:52Z",
"decision_ready": true
}

Pending Response

When the action is still awaiting approval:

{
"action_id": 12346,
"status": "pending_approval",
"risk_score": 75.0,
"timestamp": "2026-01-20T14:30:55Z",
"decision_ready": false
}

Response Fields

FieldTypeDescription
action_idintegerThe action identifier
statusstringCurrent status: approved, pending_approval, denied, processing
risk_scorefloatCalculated risk score (0-100)
timestampstringISO 8601 timestamp of the action
decision_readybooleantrue when status is approved or denied

Status Values

StatusDescriptionDecision Ready
processingAction is being evaluatedNo
pending_approvalAwaiting human approvalNo
approvedAction has been approvedYes
deniedAction has been deniedYes

Errors

CodeDescription
401Unauthorized - missing or invalid credentials
404Not found - action does not exist or belongs to different organization
500Internal server error

Not Found Error (404):

{
"detail": "Action 12345 not found",
"error_code": "ACTION_NOT_FOUND",
"status": 404
}

Polling Best Practices

  1. Start with shorter intervals for urgent actions
  2. Use exponential backoff for long-running approvals
  3. Set a maximum timeout to avoid infinite polling
  4. Consider webhooks for production use

Example Polling Implementation

import time

def wait_for_decision(client, action_id, timeout_seconds=300, initial_interval=2):
"""
Poll for action decision with exponential backoff.

Args:
client: AscendClient instance
action_id: ID of the action to poll
timeout_seconds: Maximum time to wait (default: 5 minutes)
initial_interval: Initial polling interval in seconds

Returns:
Final status response

Raises:
TimeoutError: If decision not reached within timeout
"""
start_time = time.time()
interval = initial_interval
max_interval = 30 # Cap at 30 seconds

while time.time() - start_time < timeout_seconds:
status = client.actions.get_status(action_id)

if status.decision_ready:
return status

# Exponential backoff with cap
time.sleep(interval)
interval = min(interval * 1.5, max_interval)

raise TimeoutError(f"Decision not reached within {timeout_seconds}s")

Examples

cURL

curl -X GET https://pilot.owkai.app/api/v1/actions/12345/status \
-H "X-API-Key: owkai_admin_aBcDeFgHiJkLmNoPqRsTuVwXyZ123456789"

Python

from ascend import AscendClient

client = AscendClient(api_key="owkai_admin_...")

# Submit action
result = client.actions.submit(
agent_id="my-agent",
action_type="database_query",
description="Query sensitive data",
tool_name="postgresql"
)

if result.status == "pending_approval":
print(f"Waiting for approval on action {result.id}...")

# Poll for decision
while True:
status = client.actions.get_status(result.id)

if status.decision_ready:
if status.status == "approved":
print("Action approved! Proceeding...")
# Execute the action
else:
print(f"Action denied: {status.status}")
break

time.sleep(5) # Poll every 5 seconds

Node.js

import { AscendClient } from '@anthropic/ascend-sdk';

const client = new AscendClient({ apiKey: 'owkai_admin_...' });

// Submit action
const result = await client.actions.submit({
agentId: 'my-agent',
actionType: 'database_query',
description: 'Query sensitive data',
toolName: 'postgresql'
});

if (result.status === 'pending_approval') {
console.log(`Waiting for approval on action ${result.id}...`);

// Poll for decision
const pollForDecision = async (actionId, maxAttempts = 60) => {
for (let i = 0; i < maxAttempts; i++) {
const status = await client.actions.getStatus(actionId);

if (status.decisionReady) {
return status;
}

await new Promise(resolve => setTimeout(resolve, 5000));
}
throw new Error('Timeout waiting for decision');
};

const finalStatus = await pollForDecision(result.id);
console.log(`Final status: ${finalStatus.status}`);
}

Python (requests)

import requests
import time

API_KEY = "owkai_admin_..."
BASE_URL = "https://pilot.owkai.app"

def get_action_status(action_id):
response = requests.get(
f"{BASE_URL}/api/v1/actions/{action_id}/status",
headers={"X-API-Key": API_KEY}
)
response.raise_for_status()
return response.json()

def wait_for_approval(action_id, timeout=300):
start = time.time()
while time.time() - start < timeout:
status = get_action_status(action_id)

if status["decision_ready"]:
return status

print(f"Status: {status['status']} - waiting...")
time.sleep(5)

raise TimeoutError("Approval timeout exceeded")

# Usage
action_id = 12345
final_status = wait_for_approval(action_id)
print(f"Decision: {final_status['status']}")

Alternative: Using Webhooks

Instead of polling, configure webhooks for real-time notifications:

# Configure webhook to receive approval notifications
client.webhooks.create(
name="Action Decisions",
target_url="https://your-server.com/webhooks/ascend",
event_types=["action.approved", "action.denied"],
secret="your-webhook-secret"
)

# Submit action
result = client.actions.submit(...)

# Your webhook endpoint will receive:
# {
# "event": "action.approved",
# "action_id": 12345,
# "timestamp": "2026-01-20T14:35:00Z",
# "approved_by": "admin@company.com"
# }