Skip to Content
API ReferenceAuthentication

Authentication

GoConverso uses Supabase Auth  for all authentication. This gives you JWT-based sessions, multiple OAuth providers, and secure row-level access to your data.

Authentication methods

GoConverso supports the following authentication methods:

MethodDescriptionBest for
Email & PasswordTraditional sign-up and sign-inMost users
Google OAuthOne-click sign-in with GoogleFast onboarding
OTP (One-Time Password)Email-based magic link or 6-digit codeClient portal access
API Key + JWTProgrammatic accessServer-to-server integrations

API keys

Every GoConverso project has two API keys:

Anon key (public)

The anon key is safe to use in client-side code. It respects Row Level Security policies, meaning users can only access data they are authorized to see.

apikey: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Service role key (secret)

The service role key bypasses all RLS policies and grants full database access. Use this only in server-side code, edge functions, or secure backend environments.

Never expose the service role key in client-side code. This key has unrestricted access to your entire database, including all user data. Store it in environment variables and use it only in server-side contexts.

JWT tokens

When a user signs in, Supabase issues a JSON Web Token (JWT) that contains the user’s ID, email, and metadata. This token is used to authenticate subsequent API requests.

Token structure

A decoded GoConverso JWT contains:

{ "sub": "550e8400-e29b-41d4-a716-446655440000", "email": "user@example.com", "role": "authenticated", "aud": "authenticated", "exp": 1706540400, "iat": 1706536800, "user_metadata": { "full_name": "Maria Silva", "username": "mariasilva", "niche": "barber" } }

Token lifecycle

EventBehavior
Sign inAccess token + refresh token issued
Access token expiresAuto-refreshed using refresh token (default: 1 hour)
Refresh token expiresUser must sign in again (default: 7 days)
Sign outBoth tokens invalidated

Authenticating requests

Every API request must include two headers:

curl -X GET "https://<project-id>.supabase.co/rest/v1/bookings" \ -H "apikey: <your-anon-key>" \ -H "Authorization: Bearer <jwt-access-token>" \ -H "Content-Type: application/json"
  • apikey — identifies your project (use the anon key)
  • Authorization — identifies the authenticated user (use the JWT access token)

Sign up with email and password

Create the user account

const { data, error } = await supabase.auth.signUp({ email: 'newuser@example.com', password: 'secure-password-123', options: { data: { full_name: 'New User', username: 'newuser', niche: 'personal_trainer' } } })

Handle the response

On success, the response includes the new user object and a session:

{ "user": { "id": "550e8400-e29b-41d4-a716-446655440000", "email": "newuser@example.com", "user_metadata": { "full_name": "New User", "username": "newuser", "niche": "personal_trainer" } }, "session": { "access_token": "eyJhbGciOiJIUzI1NiIs...", "refresh_token": "v1.MjA5Nj...", "expires_in": 3600 } }

Profile auto-creation

GoConverso automatically creates a profiles row when a new user signs up. This is handled by a database trigger, so no additional API call is needed.

Sign in with email and password

const { data, error } = await supabase.auth.signInWithPassword({ email: 'user@example.com', password: 'secure-password-123' }) if (error) { console.error('Sign in failed:', error.message) return } // Access token for API requests const accessToken = data.session.access_token

OAuth with Google

GoConverso supports Google OAuth for one-click sign-in. This is the recommended method for the fastest user onboarding experience.

Initiate the OAuth flow

const { data, error } = await supabase.auth.signInWithOAuth({ provider: 'google', options: { redirectTo: 'https://converso.pro/auth/callback', queryParams: { access_type: 'offline', prompt: 'consent' } } })

Handle the callback

After the user authorizes your app, they are redirected to your callback URL with an authorization code. The Supabase client automatically exchanges this for a session.

// In your callback page (e.g., /auth/callback) const { data: { session }, error } = await supabase.auth.getSession() if (session) { // User is authenticated console.log('Signed in as:', session.user.email) }

Access Google Calendar (optional)

If you need Google Calendar integration, request additional scopes during the OAuth flow:

const { data, error } = await supabase.auth.signInWithOAuth({ provider: 'google', options: { redirectTo: 'https://converso.pro/auth/callback', scopes: 'https://www.googleapis.com/auth/calendar.events' } })

OTP authentication (Client Portal)

GoConverso uses OTP-based authentication for the client portal. Clients receive a 6-digit code via email to access their portal without needing a password.

// Request OTP const response = await fetch( 'https://<project-id>.supabase.co/functions/v1/send-portal-otp', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: 'client@example.com', professionalId: '<professional-uuid>' }) } ) // Verify OTP const verify = await fetch( 'https://<project-id>.supabase.co/functions/v1/verify-portal-otp', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: 'client@example.com', code: '123456', professionalId: '<professional-uuid>' }) } )

OTP codes expire after 10 minutes and can only be used once. If a client requests a new code, any previously issued codes are automatically invalidated.

Session management

The Supabase client library handles session management automatically, including token refresh. You can listen for auth state changes:

supabase.auth.onAuthStateChange((event, session) => { switch (event) { case 'SIGNED_IN': console.log('User signed in:', session.user.email) break case 'SIGNED_OUT': console.log('User signed out') break case 'TOKEN_REFRESHED': console.log('Token refreshed') break } })

Sign out

const { error } = await supabase.auth.signOut()

Security best practices

  • Store tokens securely — Use httpOnly cookies or secure storage. Never store JWTs in localStorage for sensitive applications.
  • Use the anon key on the client — The anon key is scoped by RLS policies. Never use the service role key in browser code.
  • Validate tokens server-side — If you build custom endpoints, verify the JWT signature using your project’s JWT secret.
  • Enable RLS on all tables — GoConverso has RLS enabled by default. Never disable it without understanding the implications.
  • Rotate keys periodically — If you suspect a key has been compromised, rotate it immediately in the Supabase dashboard.

Next, learn how to work with Webhooks to receive real-time event notifications.