> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runalloy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> Learn how to authenticate with the Connectivity API across all three authentication layers

The Connectivity API uses a multi-layered authentication model to provide security, flexibility, and proper credential isolation. Understanding these layers is essential for building secure integrations.

## Authentication Layers

Authentication in the Alloy Automation API operates at three distinct levels:

```mermaid theme={null}
graph TD
    A[Your Application] -->|API Key| B[Alloy Automation Platform]
    B -->|User ID & Credential ID| C[Third-Party Platform]
```

1. **Platform Authentication**: Your application authenticates with Alloy Automation using an API key
2. **User Context**: Each request specifies which user's credentials to use
3. **Connector Credentials**: Alloy Automation uses stored credentials to authenticate with third-party platforms

## Platform Authentication

### API Key

All requests to the Connectivity API require an API key passed via the `Authorization` header using Bearer token format.

```bash theme={null}
curl https://production.runalloy.com/connectors \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "x-api-version: {API_VERSION}"
```

**Security Best Practices:**

* **Never expose your API key in client-side code** - Always make API calls from your backend
* Store API keys in environment variables or secure secret management systems
* Rotate API keys periodically
* Use different API keys for development, staging, and production environments

### Required Headers

Every API request must include these headers:

| Header          | Value                 | Description                                          |
| --------------- | --------------------- | ---------------------------------------------------- |
| `Authorization` | `Bearer YOUR_API_KEY` | Authenticates your application with Alloy Automation |
| `x-api-version` | `{API_VERSION}`       | Specifies the API version to use                     |
| `Content-Type`  | `application/json`    | Required for POST/PUT requests                       |

## User Context Authentication

### User ID Header

Operations that execute actions or manage credentials require specifying which user's context to operate within. This is done via the `x-alloy-userid` header.

```bash theme={null}
curl -X POST https://production.runalloy.com/connectors/hubspot/actions/createContact/execute \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "x-api-version: {API_VERSION}" \
  -H "x-alloy-userid: 68c3229752345278627ae373" \
  -H "Content-Type: application/json" \
  -d '{
    "credentialId": "68d2e2fd5aa2c97c2ae99c24",
    "requestBody": {
      "firstName": "Jane",
      "lastName": "Doe",
      "email": "jane.doe@example.com"
    }
  }'
```

### When User ID Is Required

The `x-alloy-userid` header is required for:

* Executing actions (`POST /connectors/{connectorId}/actions/{actionId}/execute`)
* Creating credentials (`POST /users/{userId}/credentials`)
* Listing user-specific credentials (`GET /users/{userId}/credentials`)

It is **not required** for:

* Listing connectors (`GET /connectors`)
* Getting connector metadata (`GET /connectors/{connectorId}`)
* Getting action schemas (`GET /connectors/{connectorId}/actions/{actionId}`)
* Creating users (`POST /users`)

## Connector Credentials

### Overview

Connector credentials are the authentication tokens or API keys that Alloy Automation uses to communicate with third-party platforms on behalf of your users. These credentials are stored securely by Alloy Automation and referenced by a `credentialId`.

### Credential Types

Alloy Automation supports multiple authentication patterns:

#### OAuth 2.0

Used by most modern SaaS platforms (HubSpot, Salesforce, Notion, etc.). Alloy Automation handles the complete OAuth flow including token refresh.

**Flow:**

1. **Initiate OAuth**: Request an authorization URL
2. **User Authenticates**: Redirect user to the authorization URL
3. **Token Exchange**: Alloy Automation automatically exchanges the authorization code for access/refresh tokens
4. **Credential Created**: Credential is attached to the user and ready for use

**Example:**

```bash theme={null}
# Step 1: Initiate OAuth flow
curl -X POST https://production.runalloy.com/connectors/hubspot/credentials \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "x-api-version: {API_VERSION}" \
  -H "Content-Type: application/json" \
  -d '{
    "connectorId": "hubspot",
    "credentialType": "oauth2",
    "redirectUri": "https://your-app.com/oauth/callback"
  }'

# Response:
{
  "oauthUrl": "https://api.runalloy.com/api/strategy/connector/hubspot/authorize?userId=..."
}

# Step 2: Redirect user to oauthUrl
# Step 3: User authenticates and grants permissions
# Step 4: User is redirected back to your redirectUri
# Step 5: Alloy Automation exchanges the code and creates the credential
```

#### API Keys

Some platforms use API keys or custom authentication schemes. For these, you pass the authentication data directly.

```bash theme={null}
curl -X POST https://production.runalloy.com/users/68c3229752345278627ae373/credentials \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "x-api-version: {API_VERSION}" \
  -H "Content-Type: application/json" \
  -d '{
    "connectorId": "quickbooks",
    "credentialType": "apiKey",
    "data": {
      "apiKey": "user_provided_api_key",
      "apiSecret": "user_provided_secret"
    }
  }'
```

### Discovering Required Credentials

Before creating credentials, discover what authentication data a connector requires:

```bash theme={null}
curl https://production.runalloy.com/connectors/hubspot/credentials \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "x-api-version: {API_VERSION}"
```

**Response:**

```json theme={null}
{
  "metadata": [
    {
      "authenticationType": "oauth2",
      "inputSchema": {
        "type": "object",
        "properties": {
          "userId": {
            "type": "string"
          },
          "redirectUri": {
            "type": "string"
          }
        },
        "required": ["userId", "redirectUri"]
      }
    }
  ]
}
```

Use this schema to:

* Determine the authentication type
* Identify required fields
* Build dynamic credential collection forms
* Validate input before submission

### Using Credentials

Once a credential is created and attached to a user, reference it when executing actions:

```bash theme={null}
curl -X POST https://production.runalloy.com/connectors/hubspot/actions/listContacts/execute \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "x-api-version: {API_VERSION}" \
  -H "x-alloy-userid: 68c3229752345278627ae373" \
  -H "Content-Type: application/json" \
  -d '{
    "credentialId": "68d2e2fd5aa2c97c2ae99c24",
    "input": {
      "limit": 100
    }
  }'
```

### Credential Lifecycle

**Automatic Token Refresh:**

For OAuth credentials, Alloy Automation automatically refreshes access tokens when they expire. You don't need to handle token refresh logic.

**Credential Invalidation:**

Credentials become invalid when:

* User revokes access in the third-party platform
* OAuth tokens are manually revoked
* API keys are rotated or deleted

**Error Handling:**

When credentials are invalid, the API returns:

```json theme={null}
{
  "error": {
    "source": "CONNECTIVITY_API",
    "code": "INVALID_CREDENTIAL",
    "message": "Credential not found or has been revoked",
    "details": {
      "credentialId": "68d2e2fd5aa2c97c2ae99c24"
    }
  }
}
```

## Security Architecture

### What You Store

You are responsible for securely storing:

* **Your Alloy Automation API key** - Authenticates your application
* **User-to-Credential mappings** - Which of your users have access to which Alloy Automation `credentialId` values
* **User context** - Your own user authentication and session management

### What Alloy Automation Stores

Alloy Automation securely stores:

* **OAuth access and refresh tokens** - Encrypted at rest
* **API keys and secrets** - Encrypted at rest
* **Credential metadata** - Connector type, creation date, last used, etc.

### Recommended Architecture

```mermaid theme={null}
sequenceDiagram
    participant User
    participant YourFrontend
    participant YourBackend
    participant Alloy
    participant ThirdParty

    User->>YourFrontend: Clicks "Connect HubSpot"
    YourFrontend->>YourBackend: Request OAuth URL
    YourBackend->>Alloy: POST /connectors/hubspot/credentials
    Alloy->>YourBackend: Returns oauthUrl
    YourBackend->>YourFrontend: Returns oauthUrl
    YourFrontend->>ThirdParty: Redirect to oauthUrl
    User->>ThirdParty: Authenticates & grants permissions
    ThirdParty->>YourFrontend: Redirect to callback with code
    YourFrontend->>YourBackend: Send callback code
    YourBackend->>Alloy: Exchange complete (automatic)
    Alloy->>YourBackend: credentialId
    YourBackend->>YourBackend: Store user->credentialId mapping
    YourBackend->>YourFrontend: Success
```

**Key Principles:**

1. **API keys never touch the frontend** - All Alloy Automation API calls from your backend
2. **Credential IDs are safe to store** - They're useless without your API key
3. **User context is your responsibility** - Ensure users can only access their own credentials
4. **OAuth flows can initiate from frontend** - But final credential storage happens server-side

## Authentication Errors

### Common Error Scenarios

#### Invalid API Key

```json theme={null}
{
  "message": "Invalid Authorization"
}
```

**Solution**: Verify your API key is correct and has not been rotated.

#### Missing API Version Header

```json theme={null}
{
  "errorHtml": "<!DOCTYPE html>...Cannot GET /connectors..."
}
```

**Solution**: Include `x-api-version: {API_VERSION}` header in all requests.

#### Invalid User ID

```json theme={null}
{
  "error": {
    "source": "CONNECTIVITY_API",
    "code": "INVALID_USER",
    "message": "User not found",
    "details": {
      "userId": "invalid_user_id"
    }
  }
}
```

**Solution**: Ensure the user exists and the `x-alloy-userid` header is correct.

#### Invalid Credential ID

```json theme={null}
{
  "error": {
    "source": "CONNECTIVITY_API",
    "code": "INVALID_INPUT",
    "message": "Credential not found",
    "details": {}
  }
}
```

**Solution**: Verify the credential exists, belongs to the specified user, and hasn't been revoked.

## Testing Authentication

### Verify Platform Access

Test your API key by listing available connectors:

```bash theme={null}
curl https://production.runalloy.com/connectors \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "x-api-version: {API_VERSION}"
```

Successful response indicates your API key is valid.

### Test User Context

Create a test user and verify it was created:

```bash theme={null}
# Create user
curl -X POST https://production.runalloy.com/users \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "x-api-version: {API_VERSION}" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "test_user_001",
    "fullName": "Test User"
  }'

# Response includes userId
{
  "userId": "68c3229752345278627ae373"
}
```

### Test Credential Flow

Use a sandbox account (HubSpot developer account, Notion personal workspace) to test the complete credential flow without affecting production data.

## Next Steps

* Learn about [Users](/connectivity-api/users) and how to manage end-user contexts
* Explore [Credentials](/connectivity-api/credentials) in depth
* Start [Executing Actions](/connectivity-api/quick-start#step-4%3A-execute-an-action) with stored credentials
* Review [Security Best Practices](/mcp/security/authentication-security)

## Need Help?

* [API Reference](/reference/connectivity-api/connectivity-api)
* [Support](mailto:support@runalloy.com)
* [API Status](https://status.runalloy.com)
