Skip to content

email endpoints

These two API allow you to authenticate a user using a magic link.

MethodRessourcesDescription
POST/email/requestsSend an authentication request
POST/email/tokensExchange an authorization code to an access_token

POST /email/requests

This endpoint send an authentication request to the provided user’s email. The user is sent back 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 (optional). If not specified, 'EN' will be used.
code_challenge?: string; // Optional: an hashed random string (random string -> sha256 -> url safe base64).
}

Response

type Response = {
expires_at: string; // the unix time before this authentication request expires
};

Response Codes

CodeDescription
200You did great.
400Malformed request. Could be a malformed email or callback url. Important: callback url must use https.
429Too many auth requests. The user must retry after retry_at. Could append if too many requests are made against a specific email address or from an abusing 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 prevent the authorization code to be intercepted (URL scheme spoofing on app, malicious browser extension, web server logs, etc.) you can generate a random string and send the associated hash result (code_challenge) to the authenticate 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 urlsafe base64
const digest64 = btoa(String.fromCharCode(...new Uint8Array(digest)))
.replace(/=/g, "")
.replace(/\+/g, "-")
.replace(/\//g, "_");
// pass it to the server along with the authenticate 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 with this following API endpoint.

The authorization code is valid only one time and up to 20 minutes: Your users have to click on the authorization button before this delay to grant the 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
200You are awesome!
400Malformed request.
401The authorization code is invalid (malformed or expired) or has already been used.

Usage

// retrieve the code paramater from your url.
// ...
// pass it to the server along with the authenticate request
await fetch("https://api.nopwd.io/v0/email/tokens", {
method: "POST",
body: JSON.stringify({
code, // the code parameter from your callback url
}),
});