API Documentation

Learn how to integrate MagicAuth passwordless authentication into your application in minutes.

Quick Start

Base URL: https://magicauth.app/api

1. Get Your API Key

Sign up at magicauth.app/dashboard and create an app to get your API key.

2. Send a Magic Link

POST /api/send-link
Content-Type: application/json

{
  "email": "user@example.com",
  "app_key": "your_app_key_here",
  "redirect_url": "https://yourapp.com/dashboard"
}

3. User Clicks Link in Email

They're redirected to: https://yourapp.com/dashboard?magic_token=xxx

4. Verify the Token

POST /api/verify-token
Content-Type: application/json

{
  "token": "xxx",
  "app_key": "your_app_key_here"
}

5. Done! User is Authenticated

Create a session on your backend using the verified user data.

Verify Token

POST /api/verify-token

Request Body

{
  "token": "abc123...",              // Required (from URL param)
  "app_key": "your_app_key"          // Required
}

Success Response (200 OK)

{
  "success": true,
  "user": {
    "id": 123,
    "email": "user@example.com",
    "name": null,
    "email_verified_at": "2025-11-13T12:30:00Z",
    "last_login_at": "2025-11-13T12:45:00Z"
  },
  "token": "jwt_token_here",
  "redirect_url": "https://yourapp.com/dashboard"
}

Error Responses

// Invalid token
{
  "success": false,
  "error": "Invalid token"
}

// Token already used
{
  "success": false,
  "error": "Token already used"
}

// Token expired (default: 15 minutes)
{
  "success": false,
  "error": "Token expired"
}

Code Examples

JavaScript / Node.js

// Send magic link
async function sendMagicLink(email) {
  const response = await fetch('https://magicauth.app/api/send-link', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      email: email,
      app_key: process.env.MAGICAUTH_APP_KEY,
      redirect_url: 'https://yourapp.com/auth/callback'
    })
  });

  const data = await response.json();
  return data;
}

// Verify token (in your /auth/callback route)
app.get('/auth/callback', async (req, res) => {
  const token = req.query.magic_token;

  const response = await fetch('https://magicauth.app/api/verify-token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      token: token,
      app_key: process.env.MAGICAUTH_APP_KEY
    })
  });

  const data = await response.json();

  if (data.success) {
    // Create session for user
    req.session.user = data.user;
    res.redirect('/dashboard');
  } else {
    res.redirect('/login?error=' + data.error);
  }
});

PHP / Laravel

// Send magic link
public function sendMagicLink(Request $request)
{
    $response = Http::post('https://magicauth.app/api/send-link', [
        'email' => $request->email,
        'app_key' => env('MAGICAUTH_APP_KEY'),
        'redirect_url' => url('/auth/callback')
    ]);

    return $response->json();
}

// Verify token
public function callback(Request $request)
{
    $token = $request->query('magic_token');

    $response = Http::post('https://magicauth.app/api/verify-token', [
        'token' => $token,
        'app_key' => env('MAGICAUTH_APP_KEY')
    ]);

    $data = $response->json();

    if ($data['success']) {
        Auth::loginUsingId($data['user']['id']);
        return redirect('/dashboard');
    }

    return redirect('/login')->with('error', $data['error']);
}

Python / Flask

import requests
import os

# Send magic link
@app.route('/send-link', methods=['POST'])
def send_magic_link():
    response = requests.post('https://magicauth.app/api/send-link', json={
        'email': request.json['email'],
        'app_key': os.environ['MAGICAUTH_APP_KEY'],
        'redirect_url': 'https://yourapp.com/auth/callback'
    })
    return response.json()

# Verify token
@app.route('/auth/callback')
def callback():
    token = request.args.get('magic_token')

    response = requests.post('https://magicauth.app/api/verify-token', json={
        'token': token,
        'app_key': os.environ['MAGICAUTH_APP_KEY']
    })

    data = response.json()

    if data['success']:
        session['user'] = data['user']
        return redirect('/dashboard')

    return redirect('/login?error=' + data['error'])

Error Handling

400 Bad Request

Missing required fields or invalid data

401 Unauthorized

Invalid app_key

403 Forbidden

App disabled or redirect URL not whitelisted

429 Too Many Requests

Monthly limit exceeded - upgrade your plan

500 Internal Server Error

Something went wrong on our end

Rate Limits

Plan Links/Month Burst Limit Ads
Free Forever Unlimited 100/minute Sponsored emails + in-page ads
Custom Unlimited Custom Ad-free (contact sales)

Security Best Practices

✓ Always use HTTPS

Never send API keys over HTTP

✓ Whitelist redirect URLs

Configure allowed domains in your dashboard to prevent phishing

✓ Store app_key securely

Use environment variables, never commit to git

✓ Verify tokens server-side

Never trust client-provided authentication - always verify with our API

✓ Tokens are single-use

Each token can only be verified once and expires after 15 minutes

Ready to Get Started?

Create your free account and start sending magic links in minutes

Get Your API Key