Invitations

Invite someone to your app by email. Hypery sends one email in your brand. Its button opens Hypery's sign-in page, where the invited address continues with no second email, or the person picks any other account.

An invitation is how your app brings a person in by email: "Sam invited you to edit Launch plan", "Join the Acme team", "Your client shared a proof with you".

You call one endpoint from your server, and Hypery emails the person in your app's name and brand. The button opens your page, and your page starts your normal OAuth sign-in. Hypery's sign-in page then shows every way to sign in, plus one more at the top of the email section:

  • Continue as invited address. Signs that address in straight away, creating the account if there isn't one. There is no "check your inbox" step, because opening the invitation already proved the person reads that inbox.
  • Any other method: Google, GitHub, Apple, a password, a passkey, or a different email address. This is the usual sign-in, so the person can accept your invitation with whichever account they want.

Either way the sign-in completes back to your app, and you attach the invitation to whichever account comes back.

your server
POST /api/oauth/invitations
email
sent by Hypery, in your brand
your page
return_to, starts sign-in
Hypery sign-in
continue as invited, or any method
your app
signed in

Why Hypery sends the email

Opening the invitation is what lets the invited address skip the sign-in email, so the link must only ever reach that inbox. If your app could create such a link itself, anyone holding your client secret could sign in as any Hypery user. Instead your app supplies the words and the landing page, and Hypery delivers the link to the address.

At a glance

EndpointPOST https://hypery.ai/api/oauth/invitations (server-to-server)
AuthYour app's client_id + client_secret
EmailSent by Hypery as "Your App via Hypery", with your name, logo and colour
ButtonOpens your return_to page, which starts your normal OAuth sign-in
Sign-in choicesContinue as invited address (no second email), or any other method
Lifetime7 days; "Continue as" works once
You mustAccept the invitation for whichever account signs in

Send an invitation

POST https://hypery.ai/api/oauth/invitations
Authorization: Basic base64(client_id:client_secret)
Content-Type: application/json
 
{
  "email": "sam@example.com",
  "return_to": "https://yourapp.com/invite/9f2c?signin=1",
  "title": "Alex invited you to edit “Launch plan”",
  "message": "Alex shared a file with you on YourApp.",
  "action_label": "Open in YourApp"
}
curl https://hypery.ai/api/oauth/invitations \
  -u "$HYPERY_CLIENT_ID:$HYPERY_CLIENT_SECRET" \
  -H "content-type: application/json" \
  -d '{
    "email": "sam@example.com",
    "return_to": "https://yourapp.com/invite/9f2c?signin=1",
    "title": "Alex invited you to edit “Launch plan”",
    "action_label": "Open in YourApp"
  }'

This is a server-to-server call. It needs your app's client_secret, which must never reach a browser. You can also send client_id and client_secret in the JSON body instead of HTTP Basic.

FieldRequiredNotes
emailyesThe invitee. Trimmed and lowercased.
return_toyesYour page the button opens (the person is not signed in to your app yet; see below). It must be on an origin you registered a redirect URI on, over https; http://localhost works for development. Any path and query string on that origin is allowed.
titleyesThe email's subject and heading. Up to 140 characters.
messagenoA paragraph under the heading, up to 600 characters. Line breaks are kept.
action_labelnoThe button's label. Defaults to "Open Your App".

All text is plain: Hypery escapes it, so HTML is shown as written. The email uses your app's name, logo and brand colour from its app settings, is sent as "Your App via Hypery". It tells the person they can continue with the invited address or use any other account.

Response

{ "sent": true, "expires_at": "2026-10-09T17:00:00.000Z" }
StatuserrorMeaning
400invalid_requestA field is missing or invalid (the description says which).
400invalid_return_toreturn_to is not on one of your registered redirect-URI origins.
401invalid_clientMissing or wrong client_id / client_secret.
429rate_limitedToo many invitations from your app, or to this address.
502delivery_failedThe email could not be sent. Retry later.

The page at return_to

The person arrives signed out of your app. Start your usual sign-in. With @hyperyai/sdk, that's login(), as a full-page redirect; a popup needs a click:

"use client";
import { useEffect } from "react";
import { useAuth } from "@hyperyai/sdk";
 
export function InviteLanding() {
  const { user, isLoading, login } = useAuth();
  useEffect(() => {
    if (isLoading) return;
    if (!user) {
      // Remember this page so your OAuth callback can come back to it.
      localStorage.setItem("return-to", window.location.pathname);
      void login();
    }
    // Signed in: accept the invitation for this account, then show what it was for.
  }, [isLoading, user, login]);
  return null;
}
  • Accept the invitation for whichever account signs in. Put your own reference in return_to (an invite id, or a signed token) so the page knows which invitation it is accepting. Don't require the account's email to match the invited address: the person may choose another account.
  • New people see Hypery's one-time "Allow Your App" consent screen after signing in. People who have used your app before go straight through.
  • Show a normal sign-in button too, for someone who cancels or comes back later.

How "Continue as" works

  1. The email's button opens a Hypery link, not your page directly. Hypery stores the invitation in an http-only cookie in this browser, for one hour, then forwards to return_to. Nobody is signed in by this step.
  2. Your page starts OAuth, and Hypery's sign-in page asks whether this browser has an unused invitation. If it does, the email section shows Continue as address, with every other method still below it.
  3. Choosing Continue as uses the invitation up and signs that address in, creating a verified account if there isn't one. Sign-in then continues to your app exactly like any email sign-in.

Opening the invitation on another device or in another browser, or more than an hour later, simply shows the normal sign-in page. The person can still use any method, including the usual emailed sign-in link.

If the account has two-factor authentication, Hypery still asks for the code after Continue as. The invitation proves the inbox, not the second factor.

Security

  • Only Hypery can mint the shortcut. Your app never sees a link that signs anyone in, so a leaked client_secret can send invitations (rate-limited) but cannot take over accounts.
  • return_to is pinned to your origins. Hypery refuses any return_to that isn't on an origin you registered a redirect URI on, so invitations can't be used to send people elsewhere.
  • Plain text only. Your title, message and action_label are escaped. They can't add links or markup to the email.
  • Your users stay in control. Nothing happens on click; the person always chooses how to sign in.

Testing locally

  • Register http://localhost:<port>/callback (or your dev callback) as a redirect URI, and use a return_to on that same origin.
  • Without an email provider configured, a local Hypery prints the email, including its link, to the server console instead of sending it.
  • Open the link in the same browser you'll sign in with, so Continue as appears.

Common questions

The person already has an account. Send the invitation the same way. Continue as signs them in to their existing account, and any other method works too.

They signed in with a different account than the one I invited. That's allowed by design: accept the invitation for the account that came back. If your app needs the exact invited address (for example, regulated access), check the signed-in email on your side and explain what to do if it differs.

Can I resend? Yes. Each call sends a new email with its own 7-day invitation, within the limits. Older invitations keep working until they expire or are used.

Can I withdraw an invitation? Not through Hypery. Keep the state on your side, the reference in return_to, and refuse it on your page once withdrawn. The email still opens your page, which then says so.

Expiry and reuse

  • An invitation lasts 7 days. Continue as works once.
  • Clicking the email again still lands on return_to, and the person signs in the usual way.
  • After 7 days, the button shows an "invitation expired" page. Send a new invitation.

Limits

  • Per app: 60 invitations a minute, 600 an hour, 5,000 a day.
  • Per recipient address, across all apps: 5 a minute, 20 an hour, 50 a day.

Over either limit, the call returns 429. Don't retry in a loop; wait and try later.

  • OAuth: the sign-in your return_to page starts.
  • Apps: the name, logo, colour and redirect URIs the email and return_to check use.
  • Connected apps: what people see on their side.
  • Scopes