Authentication

Relay uses Supabase Auth for authentication, supporting multiple sign-in methods including magic links, email/password, and OAuth providers.

For the External REST API (/api/v1), use API keys instead of session cookies.

Authentication Methods

Magic Link (Email OTP)

Send a one-time login link to the user's email address.

Procedure: auth.signInWithEmail

Input:

{
  email: string;        // User's email address
  redirectTo?: string;  // URL to redirect after authentication
}

Example:

curl -X POST "https://your-domain.com/api/trpc/auth.signInWithEmail" \
  -H "Content-Type: application/json" \
  -d '{"json":{"email":"user@example.com"}}'

Response:

{
  "result": {
    "data": {
      "json": {
        "success": true
      }
    }
  }
}

The user will receive an email with a login link. Clicking the link authenticates them and establishes a session.


Email & Password

Sign in with email and password credentials.

Procedure: auth.signInWithPassword

Input:

{
  email: string;     // User's email address
  password: string;  // Password (minimum 6 characters)
}

Example:

curl -X POST "https://your-domain.com/api/trpc/auth.signInWithPassword" \
  -H "Content-Type: application/json" \
  -d '{"json":{"email":"user@example.com","password":"securepassword"}}'

Response:

{
  "result": {
    "data": {
      "json": {
        "success": true,
        "user": {
          "id": "uuid",
          "email": "user@example.com",
          "created_at": "2024-01-15T10:30:00.000Z"
        }
      }
    }
  }
}

Google OAuth

Initiate Google OAuth sign-in flow.

Procedure: auth.signInWithGoogle

Input:

{
  redirectTo?: string;  // URL to redirect after authentication
}

Example:

curl -X POST "https://your-domain.com/api/trpc/auth.signInWithGoogle" \
  -H "Content-Type: application/json" \
  -d '{"json":{}}'

Response:

{
  "result": {
    "data": {
      "json": {
        "url": "https://accounts.google.com/o/oauth2/..."
      }
    }
  }
}

Redirect the user to the returned URL to complete OAuth authentication.


Session Management

Get Current User

Retrieve the currently authenticated user's profile.

Procedure: auth.getUser

Authentication: Required

Example:

curl -X GET "https://your-domain.com/api/trpc/auth.getUser" \
  -H "Cookie: your-session-cookie"

Response:

{
  "result": {
    "data": {
      "json": {
        "id": "uuid",
        "email": "user@example.com",
        "name": "John Doe",
        "avatar_url": "https://...",
        "organization_id": "uuid",
        "role": "agent",
        "preferences": {},
        "created_at": "2024-01-15T10:30:00.000Z",
        "updated_at": "2024-01-15T10:30:00.000Z"
      }
    }
  }
}

Sign Out

End the current user session.

Procedure: auth.signOut

Authentication: Required

Example:

curl -X POST "https://your-domain.com/api/trpc/auth.signOut" \
  -H "Cookie: your-session-cookie"

Response:

{
  "result": {
    "data": {
      "json": {
        "success": true
      }
    }
  }
}

Profile Management

Update Profile

Update the current user's profile information.

Procedure: auth.updateProfile

Authentication: Required

Input:

{
  name?: string;                        // Display name
  avatar_url?: string;                  // Profile picture URL
  preferences?: Record<string, any>;    // User preferences object
}

Example:

curl -X POST "https://your-domain.com/api/trpc/auth.updateProfile" \
  -H "Content-Type: application/json" \
  -H "Cookie: your-session-cookie" \
  -d '{"json":{"name":"John Smith","preferences":{"theme":"dark"}}}'

Response:

{
  "result": {
    "data": {
      "json": {
        "id": "uuid",
        "email": "user@example.com",
        "name": "John Smith",
        "preferences": {"theme": "dark"},
        // ... other user fields
      }
    }
  }
}

Password Management

Set Password

Set a password for users who signed up via magic link or OAuth (who don't have a password yet).

Procedure: auth.setPassword

Authentication: Required

Input:

{
  password: string;  // New password (minimum 8 characters)
}

Example:

curl -X POST "https://your-domain.com/api/trpc/auth.setPassword" \
  -H "Content-Type: application/json" \
  -H "Cookie: your-session-cookie" \
  -d '{"json":{"password":"newsecurepassword"}}'

Response:

{
  "result": {
    "data": {
      "json": {
        "success": true
      }
    }
  }
}

Change Password

Change password for users who already have one. Requires current password verification.

Procedure: auth.changePassword

Authentication: Required

Input:

{
  currentPassword: string;  // Current password
  newPassword: string;      // New password (minimum 8 characters)
}

Example:

curl -X POST "https://your-domain.com/api/trpc/auth.changePassword" \
  -H "Content-Type: application/json" \
  -H "Cookie: your-session-cookie" \
  -d '{"json":{"currentPassword":"oldpassword","newPassword":"newpassword"}}'

Response:

{
  "result": {
    "data": {
      "json": {
        "success": true
      }
    }
  }
}

Errors:

  • UNAUTHORIZED: Current password is incorrect

Check Has Password

Check if the current user has a password set.

Procedure: auth.hasPassword

Authentication: Required

Example:

curl -X GET "https://your-domain.com/api/trpc/auth.hasPassword" \
  -H "Cookie: your-session-cookie"

Response:

{
  "result": {
    "data": {
      "json": {
        "hasPassword": true
      }
    }
  }
}

Send Password Reset

Send a password reset email to the user.

Procedure: auth.sendPasswordReset

Input:

{
  email: string;  // User's email address
}

Example:

curl -X POST "https://your-domain.com/api/trpc/auth.sendPasswordReset" \
  -H "Content-Type: application/json" \
  -d '{"json":{"email":"user@example.com"}}'

Response:

{
  "result": {
    "data": {
      "json": {
        "success": true
      }
    }
  }
}

Account Setup

Complete Signup

Complete the signup process for new users by creating an organization and setting up their profile.

Procedure: auth.completeSignup

Authentication: Required

Input:

{
  name: string;              // User's full name (1-255 characters)
  organizationName: string;  // Organization name (1-255 characters)
  planTier: 'free' | 'pro' | 'business';  // Subscription plan (default: 'free')
}

Example:

curl -X POST "https://your-domain.com/api/trpc/auth.completeSignup" \
  -H "Content-Type: application/json" \
  -H "Cookie: your-session-cookie" \
  -d '{"json":{"name":"John Doe","organizationName":"Acme Corp","planTier":"free"}}'

Response (Free Plan):

{
  "result": {
    "data": {
      "json": {
        "user": {
          "id": "uuid",
          "email": "user@example.com",
          "name": "John Doe",
          "organization_id": "uuid",
          "role": "admin"
        },
        "organization": {
          "id": "uuid",
          "name": "Acme Corp",
          "slug": "acme-corp"
        },
        "requiresPayment": false
      }
    }
  }
}

Response (Paid Plan):

{
  "result": {
    "data": {
      "json": {
        "user": { /* ... */ },
        "organization": { /* ... */ },
        "requiresPayment": true,
        "checkoutUrl": "https://checkout.stripe.com/..."
      }
    }
  }
}

For paid plans, redirect the user to checkoutUrl to complete payment.


Rate Limiting

Authentication endpoints are rate-limited to prevent abuse:

EndpointLimit
signInWithEmail5 per minute per email
signInWithPassword5 per minute per email
signInWithGoogle5 per minute per IP
sendPasswordReset5 per minute per email

When rate limited, the API returns:

{
  "error": {
    "json": {
      "message": "Too many sign-in attempts. Please try again in X seconds.",
      "code": -32600,
      "data": {
        "code": "TOO_MANY_REQUESTS",
        "httpStatus": 429
      }
    }
  }
}

Session Cookies

After successful authentication, the server sets HTTP-only cookies for session management. Include these cookies in subsequent API requests.

For browser-based applications, cookies are automatically handled. For server-to-server integrations, you'll need to extract and store the session cookies from the authentication response.

Cookie Names:

  • sb-access-token - Access token
  • sb-refresh-token - Refresh token

Sessions are automatically refreshed when the access token expires.