Email somebody a login code

Six-digit codes and one-click links, for a wholesale portal or any page you want to keep private.

Updated · 4 min read

Where it is in the app

Open Home, choose Settings, then General › API keys.

  • Home
  • Settings
  • General
  • API keys

If you have a wholesale portal, a price list, or any page only some customers should see, you can have us email them a six-digit code and then check it when they type it in. You do not have to store anything or build a login system.

There are two shapes. A code is six digits the person types in. A link is one button in the email that takes them straight there. Both expire.

#Turning it on

  1. Verify a sending domain if you have not already — Reputation → Domains. Without one there is no address to send the code from.

  2. On WooCommerce, update our plugin to 1.0.8 or later. That is all the setup there is — the plugin already holds your key.

  3. Anywhere else, make a server key under Settings → General → API keys and keep it on your server. Never put it in a web page.

#The WooCommerce way — one line, no code

Put this on the page you want people to arrive at:

Code
[ae_code_gate purpose="wholesale_portal" redirect="/wholesale/"]

That is the whole job. The plugin asks for their email address, asks us to send the code, takes the code, checks it with us, and lets them through for twelve hours on that browser.

Then protect the page itself. One line at the top of that page's template in your theme:

Code
if ( ! ae_gate_passed( 'wholesale_portal' ) ) {
    wp_safe_redirect( home_url( '/wholesale-login/' ) );
    exit;
}

ae_gate_email( 'wholesale_portal' ) hands you back the address they proved, so the page can show that customer's own prices.

#Doing it yourself

Two requests, from your own server, with a server key from Settings → General → API keys.

Every request with a server key has to be signed — two extra headers, a timestamp and a signature made with your key. The example below does it with openssl. "Connect a custom-built store with the API" explains it, with the same thing in Node.

Ask us to send a code:

Code
KEY='PASTE-YOUR-SERVER-KEY-HERE'
BODY='{"to":"buyer@yourstore.com","purpose":"wholesale_portal"}'
TS=$(date +%s)
SIG=$(printf '%s' "$TS.$BODY" \
  | openssl dgst -sha256 -hmac "$KEY" -hex | sed 's/^.* //')
curl -sS https://app.aminoengine.com/api/v1/send/code \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -H "X-AE-Timestamp: $TS" \
  -H "X-AE-Signature: sha256=$SIG" \
  --data "$BODY"
JSON
{ "ok": true, "expires_at": "2026-09-11T14:31:07.000Z", "kind": "code", "ttl_min": 10 }

We email them the code and answer with the time it expires. We never tell you the code — the only copy that leaves us is the one in their inbox.

Then check what they typed, at https://app.aminoengine.com/api/v1/verify, with the same key, signed the same way. The body is:

JSON
{ "to": "buyer@yourstore.com", "purpose": "wholesale_portal", "code": "481920" }

The answer is either {"ok": true}, or ok: false with one word saying why: wrong, expired, locked or unknown. A wrong code is a normal answer, not an error, so your page can tell "that code is wrong" apart from "our system is down".

In WordPress the same two requests are one line each, and the plugin signs them with the key it already holds:

Code
$sent = ae_send_code( 'buyer@yourstore.com', 'wholesale_portal' );
$ok   = ae_verify_code( 'buyer@yourstore.com', 'wholesale_portal', '481920' );

purpose is just a label you choose. Use a different one for each gate you protect, so a code emailed for your wholesale portal cannot be used to get into anything else.

#The rules, so nothing surprises you

  • Codes are six digits and last ten minutes.
  • Sending a new code kills the old one immediately, even if it had time left. Never "resend just in case".
  • Five wrong tries locks that person out for fifteen minutes, and asking for a new code does not lift the lock.
  • You can ask for at most three codes for the same address in ten minutes.
  • A code works once. After it has let somebody in, it is spent.

Every code you send shows up under Messages like any other email, so you can see whether it was delivered.

#If it didn't work

  • They say the email never arrived. Look in Messages. If it says delivered, it is in their spam folder or their company's filter ate it — send them the link version instead, or read "Why emails land in spam".
  • "locked". They typed it wrong five times. They have to wait fifteen minutes. Sending a new code does not clear the lock, on purpose.
  • "unknown". Either no code was ever sent for that address and purpose, or that code has already been used. Send a new one.
  • 429 when you ask for a code. Three in ten minutes for one address is the limit. The answer says how long to wait, and the code already in their inbox still works.
  • The link version sends them to the wrong place. The page you want them to land on has to be on your own site or on a domain you have verified with us. Anything else is refused, so that a link in your customers' mail can never be pointed at a stranger's website.
  • Somebody typed the link's address in by hand and got in. They did not. The web address a link lands on proves nothing on its own, and the plugin always asks us before opening the door. If you built your own portal, make sure your server does the same.
Was this helpful?

Still stuck? A person answers.

Email support@aminoengine.com and we answer within one business day.