Skip to content

Email Endpoints

These APIs allow you to authenticate a user using a magic link.

MethodResourceDescription
POST/email/requestsSend an authentication request
POST/email/tokensExchange an authorization code for an access_token

POST /email/requests

This endpoint sends an authentication request to the provided user’s email. The user is redirected to the callback_uri URL with an authorization code.

Request Body

interface Request {
email: string; // The user's email
callback_uri: string; // The callback URL the user is redirected to
lang?: string; // Optional: The language used for the email. Defaults to 'EN' if not specified.
code_challenge?: string; // Optional: A hashed random string (random string -> sha256 -> URL-safe base64).
}

Response

type Response = {
expires_at: string; // The Unix time when this authentication request expires
};

Response Codes

CodeDescription
200Request successful.
400Malformed request. This could be due to an invalid email or callback_uri. Note: The callback URL must use https.
429Too many authentication requests. The user must retry after retry_at. This can occur if too many requests are made for a specific email address or from an abusive IP.

Usage

Simple Authentication

await fetch("https://api.nopwd.io/v0/email/requests", {
method: "POST",
body: JSON.stringify({
email: "user@email.com",
callback_uri: "https://yourwebsite.com/signin",
}),
});

Optional: With Proof Key for Code Exchange (PKCE)

For additional security and to prevent the authorization code from being intercepted (e.g., via URL scheme spoofing on apps, malicious browser extensions, web server logs), you can generate a random string and send the associated hash result (code_challenge) to the authentication endpoint.

// Assuming codeVerifier is random and stored on the client side
var digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(codeVerifier));
// Convert it to URL-safe base64
const digest64 = btoa(String.fromCharCode(...new Uint8Array(digest)))
.replace(/=/g, "")
.replace(/\+/g, "-")
.replace(/\//g, "_");
// Pass it to the server along with the authentication request
await fetch("https://api.nopwd.io/v0/email/requests", {
method: "POST",
body: JSON.stringify({
email: "user@email.com",
callback_uri: "https://yourwebsite.com/signin",
code_challenge: digest64,
}),
});

POST /email/tokens

Once the user has clicked on the link sent by email, they will be redirected to the URL defined by callback_uri with the parameter code. This can be exchanged for an access token using the following API endpoint.

The authorization code is valid only once and for up to 20 minutes. Users must click on the authorization link within this time frame to grant access.

Request Body

interface Request {
code: string; // The authorization code parameter from your callback URL
code_verifier?: string; // Optional: The random string used during the authentication step
}

Response

interface Response {
access_token: string;
}

The access token is valid for 10 minutes.

Response Codes

CodeDescription
200Request successful.
400Malformed request.
401The authorization code is invalid (malformed, expired, or already used).

Usage

// Retrieve the code parameter from your URL.
// ...
// Pass it to the server along with the authentication request
await fetch("https://api.nopwd.io/v0/email/tokens", {
method: "POST",
body: JSON.stringify({
code, // The code parameter from your callback URL
}),
});