Skip to main content

Overview

The Actions API enables you to implement custom business logic during critical authentication and user registration events. You can approve, deny, or modify these flows in real-time based on your application’s requirements.
Actions work through webhooks. WorkOS sends action requests to your endpoint, you process them, and return a signed response to approve or deny the action.

Methods

constructAction

Verifies and constructs an action context from an incoming webhook payload.
options
object
required
Options for constructing and verifying the action
ActionContext
object
The verified action context

Example

import { WorkOS } from '@workos-inc/node';
import express from 'express';

const app = express();
const workos = new WorkOS('sk_example_123456789');

app.post('/actions/authentication', express.raw({ type: 'application/json' }), async (req, res) => {
  const signature = req.headers['workos-signature'] as string;
  const secret = 'wh_secret_123456789';
  
  try {
    const action = await workos.actions.constructAction({
      payload: JSON.parse(req.body.toString()),
      sigHeader: signature,
      secret,
      tolerance: 30000,
    });
    
    // Process the action based on type
    if (action.object === 'authentication_action_context') {
      console.log('User attempting to sign in:', action.user.email);
      // Add your custom logic here
    }
  } catch (error) {
    console.error('Invalid action signature:', error);
    return res.status(400).send('Invalid signature');
  }
});

signResponse

Creates a signed response to approve or deny an action.
data
AuthenticationActionResponseData | UserRegistrationActionResponseData
required
The response data to sign
secret
string
required
Your webhook secret for signing the response
response
object
The signed response object

Example - Allow Authentication

const response = await workos.actions.signResponse(
  {
    type: 'authentication',
    verdict: 'Allow',
  },
  'wh_secret_123456789',
);

res.json(response);

Example - Deny Authentication

const response = await workos.actions.signResponse(
  {
    type: 'authentication',
    verdict: 'Deny',
    errorMessage: 'Your account has been suspended. Please contact support.',
  },
  'wh_secret_123456789',
);

res.json(response);

Example - Conditional Logic

app.post('/actions/authentication', express.raw({ type: 'application/json' }), async (req, res) => {
  const signature = req.headers['workos-signature'] as string;
  const secret = 'wh_secret_123456789';
  
  const action = await workos.actions.constructAction({
    payload: JSON.parse(req.body.toString()),
    sigHeader: signature,
    secret,
  });
  
  // Example: Block authentication from specific IP ranges
  const blockedIpRanges = ['192.168.1.', '10.0.0.'];
  const isBlockedIp = blockedIpRanges.some(range => 
    action.ipAddress?.startsWith(range)
  );
  
  const response = await workos.actions.signResponse(
    {
      type: 'authentication',
      verdict: isBlockedIp ? 'Deny' : 'Allow',
      errorMessage: isBlockedIp 
        ? 'Authentication from this network is not permitted.'
        : undefined,
    },
    secret,
  );
  
  res.json(response);
});

verifyHeader

Verifies the signature of an incoming webhook request. This method is available as a standalone utility.
options
object
required
Verification options

Example

try {
  await workos.actions.verifyHeader({
    payload: req.body,
    sigHeader: req.headers['workos-signature'] as string,
    secret: 'wh_secret_123456789',
    tolerance: 30000,
  });
  console.log('Signature verified');
} catch (error) {
  console.error('Invalid signature');
}

Use Cases

IP Allowlisting

Restrict authentication to specific IP addresses or networks

Email Domain Validation

Ensure users register with approved email domains

Account Suspension

Prevent suspended users from authenticating

Custom Onboarding

Add users to external systems during registration

Fraud Prevention

Block suspicious registration patterns or device fingerprints

Conditional Access

Implement time-based or location-based access controls

Best Practices

Always verify webhook signatures using constructAction or verifyHeader before processing action requests.
Actions must respond within 3 seconds. Implement async processing for time-consuming operations and return a cached or default response immediately.
When denying an action, provide clear errorMessage text to help users understand why their request was denied and what they can do to resolve it.

Webhooks

Configure webhook endpoints for Actions

User Management

Manage users and authentication

Build docs developers (and LLMs) love