Documentation · v1

Intégrer Genuka Auth

Ajoutez l'auth WhatsApp à votre app en moins de 10 minutes. Pas de mot de passe, pas d'OTP — un clic, un message, un profil vérifié.

Overview

Genuka Auth is an OAuth2-style identity provider that uses WhatsApp as its single channel. Your application redirects the user to Genuka, the user sends one pre-filled WhatsApp message, and Genuka returns a short-lived authorization code your backend exchanges for the user profile.

  • No passwords stored, no OTP codes typed.
  • Verified phone number on every login.
  • Each company isolates its own customer base.
  • Codes are single-use and expire after 15 minutes.

Quickstart

  1. Create your company. Sign in with WhatsApp on this site — your company is provisioned automatically the first time you authenticate.
  2. Set your redirect URL. In My Company, fill in the URL where Genuka should send users back after a successful login (must accept a code query param).
  3. Generate API keys. Open Company Keys, click New Company Key, and copy the client_secret. It's shown only once.
  4. Wire it up. Redirect your users to https://auth.genuka.com/c/{COMPANY_ID}, then exchange the returned code on your backend.

Authentication flow

1. Your app  ──▶  GET  /c/{company_id}                  (Genuka)
2. Genuka    ──▶  WhatsApp link with one-time key       (User)
3. User      ──▶  Sends pre-filled WhatsApp message     (Genuka webhook)
4. Genuka    ──▶  Redirects to {redirect_url}?code=...  (Your app)
5. Your app  ──▶  POST /api/connect/exchange            (Genuka)
6. Genuka    ──▶  { subject, data: { ...profile } }     (Your app)

Exchange endpoint

Trade the authorization code for the verified user profile. Server-side only.

Request

POST https://auth.genuka.com/api/connect/exchange
Content-Type: application/json

{
    "client_id": "pk_...",
    "client_secret": "sk_...",
    "code": "01HXYZ..."
}

Response

{
    "subject": "wa:237612345678",
    "issued_at": "2026-02-01T12:00:00+00:00",
    "data": {
        "id": "01HXYZ...",
        "company_id": "01HABC...",
        "first_name": "John",
        "last_name": "Doe",
        "phone": "237612345678",
        "provider_type": "whatsapp",
        "provider_id": "237612345678",
        "metadata": {}
    }
}

Code examples

JavaScript / TypeScript

const res = await fetch('https://auth.genuka.com/api/connect/exchange', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
        client_id: process.env.GENUKA_CLIENT_ID,
        client_secret: process.env.GENUKA_CLIENT_SECRET,
        code,
    }),
});
const { data } = await res.json();

PHP / Laravel

$response = Http::post('https://auth.genuka.com/api/connect/exchange', [
    'client_id'     => config('services.genuka.client_id'),
    'client_secret' => config('services.genuka.client_secret'),
    'code'          => $request->query('code'),
])->throw()->json();

Auth::login(User::updateOrCreate(
    ['whatsapp_id' => $response['data']['provider_id']],
    ['phone'       => $response['data']['phone']],
));

cURL

curl -X POST https://auth.genuka.com/api/connect/exchange \
    -H "Content-Type: application/json" \
    -d '{"client_id":"pk_...","client_secret":"sk_...","code":"01HXYZ..."}'

Error codes

Code HTTP Meaning
invalid_client 401 client_id or client_secret is wrong, or the key is inactive.
invalid_code 400 The code does not exist or doesn't belong to this company.
expired_code 400 The code expired (15 minutes after issue).
already_used 400 The code was already exchanged.

Security

  • Never expose client_secret in client-side code or public repos.
  • Always exchange codes from your backend, over HTTPS.
  • Validate that the returned company_id matches your own.
  • Rotate keys if a secret is leaked — keys can be deactivated from Company Keys.
  • Webhooks are signed with HMAC SHA-256 using your Meta App secret.

Ready to ship?

Create your company and grab your API keys in two minutes.

Get started