> **Building with AI coding agents?** If you're using an AI coding agent, install the official Scalekit plugin. It gives your agent full awareness of the Scalekit API — reducing hallucinations and enabling faster, more accurate code generation.
>
> - **Claude Code**: `/plugin marketplace add scalekit-inc/claude-code-authstack` then `/plugin install <auth-type>@scalekit-auth-stack`
> - **GitHub Copilot CLI**: `copilot plugin marketplace add scalekit-inc/github-copilot-authstack` then `copilot plugin install <auth-type>@scalekit-auth-stack`
> - **Codex**: run the bash installer, restart, then open Plugin Directory and enable `<auth-type>`
> - **Skills CLI** (Windsurf, Cline, 40+ agents): `npx skills add scalekit-inc/skills --list` then `--skill <skill-name>`
>
> `<auth-type>` / `<skill-name>`: `agent-auth`, `full-stack-auth`, `mcp-auth`, `modular-sso`, `modular-scim` — [Full setup guide](https://docs.scalekit.com/dev-kit/build-with-ai/)

---

# Interceptor triggers

{/*
## `POST_USER_AUTHENTICATION`

Fires after a user successfully authenticates but before completing the login flow. Use this to apply post-authentication checks, validate IP addresses, or enforce conditional access policies.

### Request body from Scalekit

```json title="POST_USER_AUTHENTICATION — request body" showLineNumbers=true
{
    "display_name": "Apply conditional access policies",
    "trigger_point": "POST_USER_AUTHENTICATION",
    "interceptor_context": {
        "environment_id": "env_12345",
        "user_id": "usr_9f8c7d6e5a",
        "user_email": "alice@acmecorp.com",
        "connection_details": [
            {
                "id": "conn_2f71c0",
                "type": "PASSWORDLESS", // Authentication method that was used
                "provider": "SCALEKIT" // Provider for passwordless authentication
            }
        ],
        "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/537.36...",
        "device_type": "Desktop", // Desktop, Mobile, Tablet, or Unknown
        "ip_address": "203.0.113.45", // IP address to check against threat databases
        "region": "US", // Two-letter country code
        "triggered_at": "2025-10-08T11:19:22.423Z" // ISO 8601 timestamp
    },
    "data": {
        "user": { // User who just authenticated
            "id": "usr_9f8c7d6e5a",
            "email": "alice@acmecorp.com",
            "email_verified": true,
            "memberships": [ // Organizations this user belongs to
                {
                    "organization_id": "org_a1b2c3",
                    "status": "ACTIVE"
                }
            ],
            "custom_attributes": {}, // Custom attributes set on the user
            "raw_attributes": {} // Raw attributes from identity provider
        }
    }
}
```

### Response format to return

```json title="POST_USER_AUTHENTICATION — response body" showLineNumbers=true
{
    "decision": "DENY", // Required: ALLOW to complete login, DENY to block
    "error": {
        "message": "Login blocked: Suspicious activity detected from your location" // Shown to user when DENY
    }
}
```

*/}

## `PRE_SIGNUP`

Fires before a user creates a new organization. Use this to validate email domains, check against blocklists, or enforce custom signup policies.

### Request body from Scalekit

```json title="PRE_SIGNUP — request body" showLineNumbers=true
{
  "display_name": "Validate email domain",
  "trigger_point": "PRE_SIGNUP",
  "interceptor_context": {
    "environment_id": "env_92561807201272162",
    "user_id": "usr_93418238346728951", // Present only if user exists in another organization
    "user_email": "john.doe@acmecorp.com", // Email attempting to sign up
    "connection_details": [
      {
        "id": "conn_92561808744978132",
        "type": "OAUTH", // OAUTH, SAML, OIDC, or PASSWORDLESS
        "provider": "GOOGLE" // Identity provider used for authentication
      }
    ],
    //Contains parameters from the /oauth/authorize request
    "auth_request": {
        "connection_id": "conn_81665025441299343",
        "organization_id": "org_102953846317318346",
        "domain": "foocorp.com",
        "login_hint": "john.doe@example.com",
        "state": "xsrPHl7k7ARgdhC6"
    },
    "device_type": "Desktop", // Desktop, Mobile, Tablet, or Unknown
    "ip_address": "203.0.113.24", // Client's IP address for geolocation or blocklist checks
    "region": "IN", // Two-letter country code
    "city": "Bengaluru",
    "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36...",
    "triggered_at": "2025-10-09T09:48:02.875Z" // ISO 8601 timestamp
  },
  "data": {
    // User object present only when user already exists in another organization
    "user": {
      "id": "usr_93418238346728951",
      "name": "John Doe",
      "email": "john.doe@acmecorp.com",
      "email_verified": true,
      "created_at": "2025-10-06T11:06:49.120Z",
      "updated_at": "2025-10-06T13:33:06.479Z",
      "given_name": "John",
      "family_name": "Doe",
      "metadata": {
        "type": "social_user"
      },
      "memberships": [ // Existing organization memberships
        {
          "organization_id": "org_93418204671239864",
          "status": "ACTIVE",
          "roles": [
              "admin"
          ],
          "metadata": {
                "cost": {
                    "category": "platform",
                    "region": "US"
                },
                "department": "engineering"
          },
           "organization_name": "Example inc"
        }
      ]
    }
  }
}
```

### Response format to return

```json title="PRE_SIGNUP — response body" wrap showLineNumbers=true
{
  // Required: choose ALLOW or DENY
  "decision": "DENY", // ALLOW | DENY
  // Optional with DENY
  "error": {
    "message": "Only @acmecorp.com email addresses are allowed to sign up" // Shown to user when DENY
  },
  // Optional with ALLOW, Include when the user is to be provisioned in an existing organization.
   "response": {
        "create_organization_membership": {
            // either external_organization_id or organization_id is required
            "external_organization_id": "ext_B6YycAGRaPmnuxAFPT5KI4HBHxr4qWX",
            "organization_id": "org_102953846317318346",
            "roles": [
                "admin",
                "viewer"
            ]
        }
    }
}
```

## `PRE_SESSION_CREATION`

Fires before session tokens are issued for a user. Use this to add custom claims to tokens, apply conditional access policies, or integrate with external authorization systems.

### Request body from Scalekit

```json title="PRE_SESSION_CREATION — request body" wrap showLineNumbers=true
{
  "display_name": "Add custom claims to tokens",
  "trigger_point": "PRE_SESSION_CREATION",
  "interceptor_context": {
    "environment_id": "env_92561807204567213",
    "user_id": "usr_93418238346728951",
    "user_email": "john.doe@acmecorp.com",
    "organization_id": "org_93418204671239864", // Organization user is logging into
    "connection_details": [
      {
        "id": "conn_92561808744978132",
        "type": "OAUTH", // Authentication method used
        "provider": "GOOGLE"
      }
    ],
    "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36...",
    "device_type": "Desktop", // Desktop, Mobile, Tablet, or Unknown
    "ip_address": "203.0.113.24", // Use for conditional access based on location
    "region": "US", // Two-letter country code
    "city": "San Francisco",
    "triggered_at": "2025-10-08T15:22:42.381Z" // ISO 8601 timestamp
  },
  "data": {
    "user": {
      "id": "usr_93418238346728951",
      "name": "John Doe",
      "email": "john.doe@acmecorp.com",
      "email_verified": true,
      "created_at": "2025-10-06T11:06:49.120Z",
      "updated_at": "2025-10-06T13:33:06.479Z",
      "first_name": "John",
      "last_name": "Doe",
      "memberships": [ // All organizations this user belongs to
        {
          "organization_id": "org_93418204671239864",
          "status": "ACTIVE"
        }
      ]
    }
  }
}
```

### Response format to return

```json title="PRE_SESSION_CREATION — response body" wrap showLineNumbers=true
{
  "decision": "ALLOW", // Required: ALLOW to issue tokens, DENY to block login
  "response": {
    "claims": { // Optional: Custom claims added to both access and ID tokens
      "subscription_tier": "enterprise",
      "data_region": "us-west-2",
      "feature_flags": ["analytics_dashboard", "api_access", "custom_branding"],
      "account_manager": "jane.smith@acmecorp.com"
    }
  }
}
```
**Modify token claims in the response:** The `claims` field lets you add custom information that will be included in both access tokens and ID tokens issued by Scalekit.

## `PRE_USER_INVITATION`

Fires before an invitation is created or sent for a new organization member. Use this to validate invitee email addresses, enforce invitation policies, or check user limits.

### Request body from Scalekit

```json title="PRE_USER_INVITATION — request body" wrap showLineNumbers=true
{
    "display_name": "Validate invitation policy",
    "trigger_point": "PRE_USER_INVITATION",
    "interceptor_context": {
        "environment_id": "env_92561807201272162",
        "user_id": "usr_93418238346728951", // Present only if invitee already exists in another org
        "user_email": "sarah.johnson@contractor.com", // Email address being invited
        "organization_id": "org_93731871904672153", // Organization sending the invitation
        "city": "Bengaluru",
        "device_type": "Desktop", // Device of the person sending the invitation
        "ip_address": "182.156.5.2", // IP of the person sending the invitation
        "region": "IN", // Two-letter country code
        "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36...",
        "triggered_at": "2025-10-09T12:50:41.803Z" // ISO 8601 timestamp
    },
    "data": {
        "organization": { // Organization details for context
            "id": "org_93731871904672153",
            "name": "Acme Corp"
        }
    }
}
```

### Response format to return

```json title="PRE_USER_INVITATION — response body" wrap showLineNumbers=true
{
  "decision": "DENY", // Required: ALLOW to send invitation, DENY to block
  "error": {
    "message": "Cannot invite users from external domains. Please use @acmecorp.com email addresses." // Shown when DENY
  }
}
```

## `PRE_M2M_TOKEN_CREATION`

Fires before issuing a machine-to-machine access token. Use this to add custom claims, modify scopes dynamically, or apply conditional access rules for service-to-service authentication.

### Request body from Scalekit

```json title="PRE_M2M_TOKEN_CREATION — request body" wrap showLineNumbers=true
{
  "display_name": "Validate M2M client permissions",
  "trigger_point": "PRE_M2M_TOKEN_CREATION",
  "interceptor_context": {
    "environment_id": "env_17002334043308132",
    "client_id": "m2morg_93710427703245914", // M2M client requesting the token
    "user_agent": "deployment-service/2.1.0", // Service making the request
    "device_type": "Unknown",
    "triggered_at": "2025-10-08T21:22:20.173Z" // ISO 8601 timestamp
  },
  "data": {
    "m2m_token_claims": { // Claims that will be included in the token
      "client_id": "m2morg_93710427703245914",
      "claims": {
        "custom_claims": { // Existing custom claims from client configuration
          "service_name": "deployment-automation",
          "deployment_environment": "production"
        },
        "oid": "org_89669394174574792", // Organization ID for this M2M client
        "scope": "deploy:applications read:deployments write:logs", // Space-separated scopes
        "scopes": [ // Array of individual scopes requested
          "deploy:applications",
          "read:deployments",
          "write:logs"
        ]
      }
    }
  }
}
```

### Response format to return

```json title="PRE_M2M_TOKEN_CREATION — response body" wrap showLineNumbers=true
{
  "decision": "ALLOW", // Required: ALLOW to issue token, DENY to block
  "response": {
    "claims": { // Optional: Add or modify claims in the M2M token
      "scope": "deploy:applications read:deployments", // Can modify scopes dynamically
      "aud": "https://api.acmecorp.com", // Target audience for the token
      "rate_limit": "1000", // Custom claim for rate limiting
      "environment": "production" // Custom claim for environment context
    }
  }
}
```

---

## More Scalekit documentation

| Resource | What it contains | When to use it |
|----------|-----------------|----------------|
| [/llms.txt](/llms.txt) | Structured index with routing hints per product area | Start here — find which documentation set covers your topic before loading full content |
| [/llms-full.txt](/llms-full.txt) | Complete documentation for all Scalekit products in one file | Use when you need exhaustive context across multiple products or when the topic spans several areas |
| [sitemap-0.xml](https://docs.scalekit.com/sitemap-0.xml) | Full URL list of every documentation page | Use to discover specific page URLs you can fetch for targeted, page-level answers |
