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.
Magic Link Object
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
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier for the magic link |
contactId | string | ID of the contact this link is for |
token | string | Secure token for the magic link |
redirectUrl | string | URL to redirect after successful validation |
expiresAt | string | ISO 8601 timestamp when link expires |
usageCount | number | Number of times link has been used |
maxUsageCount | number | Maximum number of times link can be used |
isValid | boolean | Whether the link is still valid |
createdAt | string | ISO 8601 timestamp of creation |
updatedAt | string | ISO 8601 timestamp of last update |
List Magic Links for Contact
Retrieve all magic links associated with a specific contact.
GET /api/magic-links?contactId={contact_id}Headers
| Header | Required | Description |
|---|---|---|
X-API-Key | Yes | Your API key for authentication |
Content-Type | Yes | Must be application/json |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
contactId | string | Yes | The 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"Create Magic Link
Generate a new magic link for a contact.
POST /api/magic-linksRequest Body
{
"contactId": "contact_456def",
"redirectUrl": "https://example.com/dashboard",
"expiresIn": 86400,
"maxUsageCount": 1,
"metadata": {
"purpose": "password_reset"
}
}Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
contactId | string | Yes | Contact ID to create link for |
redirectUrl | string | Yes | URL to redirect after validation |
expiresIn | number | No | Seconds until expiration (default: 86400 / 24 hours) |
maxUsageCount | number | No | Max times link can be used (default: 1) |
metadata | object | No | Additional 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 Magic Link
Validate a magic link token and check if it's still usable.
POST /api/magic-links/validateRequest 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 Magic Link Usage
Track when a magic link is clicked or used.
POST /api/magic-links/track-usageRequest 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
}
}Invalidate Magic Link
Manually invalidate a magic link before it expires.
POST /api/magic-links/:link_id/invalidatePath Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
link_id | string | Yes | The 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'
}
});