Docs
Magic Links API

Magic Links API

Create, validate, and manage secure magic links for passwordless authentication and direct access.

The Magic Links API enables you to create secure, time-limited links that provide passwordless access to specific resources or actions. Magic links are commonly used for email verification, password-less login, and secure document access.

A magic link represents a secure, tokenized URL with the following structure:

{
  "id": "ml_abc123xyz789",
  "contactId": "contact_456def",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "redirectUrl": "https://example.com/dashboard",
  "expiresAt": "2025-01-16T10:30:00.000Z",
  "usageCount": 0,
  "maxUsageCount": 1,
  "isValid": true,
  "createdAt": "2025-01-15T10:30:00.000Z",
  "updatedAt": "2025-01-15T10:30:00.000Z"
}

Attributes

FieldTypeDescription
idstringUnique identifier for the magic link
contactIdstringID of the contact this link is for
tokenstringSecure token for the magic link
redirectUrlstringURL to redirect after successful validation
expiresAtstringISO 8601 timestamp when link expires
usageCountnumberNumber of times link has been used
maxUsageCountnumberMaximum number of times link can be used
isValidbooleanWhether the link is still valid
createdAtstringISO 8601 timestamp of creation
updatedAtstringISO 8601 timestamp of last update

Retrieve all magic links associated with a specific contact.

GET /api/magic-links?contactId={contact_id}

Headers

HeaderRequiredDescription
X-API-KeyYesYour API key for authentication
Content-TypeYesMust be application/json

Query Parameters

ParameterTypeRequiredDescription
contactIdstringYesThe unique identifier of the contact

Response

Status Code: 200 OK

{
  "success": true,
  "data": [
    {
      "id": "ml_abc123xyz789",
      "contactId": "contact_456def",
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
      "redirectUrl": "https://example.com/dashboard",
      "expiresAt": "2025-01-16T10:30:00.000Z",
      "usageCount": 0,
      "maxUsageCount": 1,
      "isValid": true,
      "createdAt": "2025-01-15T10:30:00.000Z"
    }
  ]
}

Example Request

curl -X GET "https://api.evon.com/api/magic-links?contactId=contact_456def" \
  -H "X-API-Key: your_api_key_here" \
  -H "Content-Type: application/json"

Generate a new magic link for a contact.

POST /api/magic-links

Request Body

{
  "contactId": "contact_456def",
  "redirectUrl": "https://example.com/dashboard",
  "expiresIn": 86400,
  "maxUsageCount": 1,
  "metadata": {
    "purpose": "password_reset"
  }
}

Parameters

ParameterTypeRequiredDescription
contactIdstringYesContact ID to create link for
redirectUrlstringYesURL to redirect after validation
expiresInnumberNoSeconds until expiration (default: 86400 / 24 hours)
maxUsageCountnumberNoMax times link can be used (default: 1)
metadataobjectNoAdditional metadata for the link

Response

Status Code: 201 Created

{
  "success": true,
  "data": {
    "id": "ml_abc123xyz789",
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "magicUrl": "https://example.com/magic?token=eyJhbGc...",
    "expiresAt": "2025-01-16T10:30:00.000Z"
  }
}

Validate a magic link token and check if it's still usable.

POST /api/magic-links/validate

Request Body

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Response

Status Code: 200 OK (Valid)

{
  "success": true,
  "valid": true,
  "data": {
    "contactId": "contact_456def",
    "redirectUrl": "https://example.com/dashboard",
    "metadata": {
      "purpose": "password_reset"
    }
  }
}

Status Code: 200 OK (Invalid)

{
  "success": false,
  "valid": false,
  "error": "LINK_EXPIRED",
  "message": "This magic link has expired"
}

Example Request

curl -X POST "https://api.evon.com/api/magic-links/validate" \
  -H "X-API-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  }'

Track when a magic link is clicked or used.

POST /api/magic-links/track-usage

Request Body

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "metadata": {
    "userAgent": "Mozilla/5.0...",
    "ipAddress": "192.168.1.1"
  }
}

Response

Status Code: 200 OK

{
  "success": true,
  "data": {
    "usageCount": 1,
    "remainingUses": 0,
    "isValid": false
  }
}

Manually invalidate a magic link before it expires.

POST /api/magic-links/:link_id/invalidate

Path Parameters

ParameterTypeRequiredDescription
link_idstringYesThe unique identifier of the magic link

Response

Status Code: 200 OK

{
  "success": true,
  "message": "Magic link invalidated successfully"
}

Example Request

curl -X POST "https://api.evon.com/api/magic-links/ml_abc123xyz789/invalidate" \
  -H "X-API-Key: your_api_key_here" \
  -H "Content-Type: application/json"

Error Responses

400 Bad Request

{
  "success": false,
  "error": "INVALID_REQUEST",
  "message": "Contact ID is required",
  "details": []
}

404 Not Found

{
  "success": false,
  "error": "CONTACT_NOT_FOUND",
  "message": "Contact not found"
}

410 Gone

{
  "success": false,
  "error": "LINK_EXPIRED",
  "message": "This magic link has expired"
}

Use Cases

Password Reset Flow

// 1. Create magic link for password reset
const response = await fetch('https://api.evon.com/api/magic-links', {
  method: 'POST',
  headers: {
    'X-API-Key': 'your_api_key_here',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    contactId: 'contact_456def',
    redirectUrl: 'https://example.com/reset-password',
    expiresIn: 3600, // 1 hour
    maxUsageCount: 1,
    metadata: { purpose: 'password_reset' }
  })
});
 
const { data } = await response.json();
 
// 2. Send magic link via email
await sendEmail(contact.email, {
  subject: 'Reset Your Password',
  magicUrl: data.magicUrl
});
 
// 3. When user clicks link, validate it
const validation = await fetch(
  'https://api.evon.com/api/magic-links/validate',
  {
    method: 'POST',
    headers: {
      'X-API-Key': 'your_api_key_here',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      token: urlParams.get('token')
    })
  }
);
 
if (validation.valid) {
  // Allow password reset
}

Email Verification

// Create one-time use magic link for email verification
const link = await createMagicLink({
  contactId: newUser.id,
  redirectUrl: 'https://example.com/verify-success',
  expiresIn: 172800, // 48 hours
  maxUsageCount: 1,
  metadata: { purpose: 'email_verification' }
});

Secure Document Access

// Create multi-use magic link for document access
const link = await createMagicLink({
  contactId: client.id,
  redirectUrl: 'https://example.com/documents/invoice-123',
  expiresIn: 604800, // 7 days
  maxUsageCount: 10, // Allow 10 views
  metadata: {
    purpose: 'document_access',
    documentId: 'invoice-123'
  }
});