TapAuth API Documentation

WhatsApp-based authentication for your mobile apps

Overview

TapAuth provides a simple WhatsApp-based authentication system for mobile applications. Your app submits the end user's WhatsApp number, the user sends a message to our bot, the bot verifies the number matches, and your app polls until the session is verified.

Base URL: https://tapauth.my.id/api

Authentication: All API requests require an API key in the X-API-KEY header. Call these endpoints from your backend only — never embed the API key in a mobile app. Your mobile app should poll your backend, and your backend proxies to TapAuth.

SDK Downloads

Use our official SDKs to integrate TapAuth quickly:

Documentation: PHP README | Node.js README

Authentication Flow

  1. Your app calls POST /v1/auth/request with the user's wa_number to initiate authentication
  2. User opens the returned WhatsApp URL and sends the message to the bot
  3. Bot detects the code and verifies the sender's number matches wa_number
  4. If it matches, the session becomes verified; the bot replies with a success message
  5. Your app polls POST /v1/auth/verify until the session is verified
  6. You receive the user's WhatsApp number and name (Rp50 is deducted)

API Endpoints

POST /v1/auth/request

Initiate an authentication session and get WhatsApp URL for user.

Headers

X-API-KEY: tap_your_api_key_here

Request Body

{
  "wa_number": "6281234567890"
}

wa_number (the end user's WhatsApp number) is required. The bot verifies that the sender matches this number.

Response (200 OK)

{
  "success": true,
  "identifier": "TAP-XXXXXXXXXXXX",
  "whatsapp_url": "whatsapp://send?phone=628123456789&text=...",
  "expires_in": 300
}

Error Responses

401 - Invalid or missing API key
402 - Insufficient balance
429 - Too many pending sessions (max 10)
503 - No bot device available
POST /v1/auth/verify

Check the session status. Once the session is verified, this returns the user info and deducts Rp50 from your balance. Poll this endpoint until it succeeds.

Headers

X-API-KEY: tap_your_api_key_here

Request Body

{
  "identifier": "TAP-XXXXXXXXXXXX"
}

Response (200 OK — verified)

{
  "status": "success",
  "wa_number": "6281234567890",
  "push_name": "John Doe"
}

Response (400 — still waiting)

While the user has not completed verification, keep polling. The reason field is waiting, or rejected if the bot found the number did not match.

{
  "error": "Session not ready for verification",
  "reason": "waiting",
  "message": "Menunggu verifikasi WhatsApp"
}

Error Responses

400 - Session not ready (reason: waiting or rejected)
401 - Invalid or missing API key
404 - Session not found

Integration

After requesting authentication, your backend should poll the verify endpoint to check if the user has completed verification via WhatsApp. Your mobile app polls your backend at an interval (e.g. every 3s), and your backend forwards the check to TapAuth using the API key.

Flow (mobile → your backend → TapAuth):

  1. Mobile app sends the user's wa_number to your backend; your backend calls /v1/auth/request and returns the identifier + WhatsApp URL
  2. Mobile app opens the WhatsApp URL for the user to send the verification message
  3. Mobile app polls your backend on an interval; your backend calls /v1/auth/verify (a 400 with reason: waiting means keep polling) until it succeeds

Pricing

Rp50

per successful authentication

New users get Rp5,000 welcome bonus (100 free authentications)

Code Examples

These examples run on your backend (the API key stays server-side). Your mobile app calls your backend, and your backend runs the request/verify polling below.

JavaScript (Fetch)

// Request authentication (send the user's WhatsApp number)
const response = await fetch('https://tapauth.my.id/api/v1/auth/request', {
  method: 'POST',
  headers: {
    'X-API-KEY': 'tap_your_api_key_here',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ wa_number: '6281234567890' })
});
const data = await response.json();

// Open WhatsApp
window.location.href = data.whatsapp_url;

// Poll verify until the session is verified
async function poll(identifier) {
  while (true) {
    const res = await fetch('https://tapauth.my.id/api/v1/auth/verify', {
      method: 'POST',
      headers: {
        'X-API-KEY': 'tap_your_api_key_here',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ identifier })
    });
    const result = await res.json();

    if (res.ok && result.status === 'success') {
      console.log(result.wa_number, result.push_name);
      return result;
    }
    if (result.reason === 'rejected') {
      throw new Error(result.message);
    }
    // reason === 'waiting' → try again shortly
    await new Promise(r => setTimeout(r, 3000));
  }
}
await poll(data.identifier);

PHP (cURL)

// Request authentication (send the user's WhatsApp number)
$ch = curl_init('https://tapauth.my.id/api/v1/auth/request');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'X-API-KEY: tap_your_api_key_here',
    'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
    'wa_number' => '6281234567890'
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = json_decode(curl_exec($ch));

// Poll verify until the session is verified
while (true) {
    $ch = curl_init('https://tapauth.my.id/api/v1/auth/verify');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'X-API-KEY: tap_your_api_key_here',
        'Content-Type: application/json'
    ]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
        'identifier' => $response->identifier
    ]));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $body = curl_exec($ch);
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $userData = json_decode($body);

    if ($code === 200 && $userData->status === 'success') {
        echo $userData->wa_number;
        break;
    }
    if (isset($userData->reason) && $userData->reason === 'rejected') {
        throw new Exception($userData->message);
    }
    sleep(3); // reason === 'waiting'
}

Python (Requests)

import requests
import time

# Request authentication (send the user's WhatsApp number)
response = requests.post(
    'https://tapauth.my.id/api/v1/auth/request',
    headers={'X-API-KEY': 'tap_your_api_key_here'},
    json={'wa_number': '6281234567890'}
)
data = response.json()

# Poll verify until the session is verified
while True:
    res = requests.post(
        'https://tapauth.my.id/api/v1/auth/verify',
        headers={'X-API-KEY': 'tap_your_api_key_here'},
        json={'identifier': data['identifier']}
    )
    result = res.json()

    if res.status_code == 200 and result.get('status') == 'success':
        print(result['wa_number'], result['push_name'])
        break
    if result.get('reason') == 'rejected':
        raise Exception(result['message'])
    time.sleep(3)  # reason == 'waiting'

Support

For questions or support, please contact us through your dashboard or email [email protected]

© 2026 TapAuth. All rights reserved.