Sign in Create account
Integrations

Auth.js (NextAuth)

Auth.js email sign-in (magic link) sent through the Postal API.

In Auth.js (NextAuth), email sign-in (magic link) uses an email provider. This provider sends through the Postal API. There is no connection to create.

#Key and sender

Create a sending-only key under API keys, store it in POSTAL_API_KEY and use a sender from a verified domain.

#The provider

auth.ts
import NextAuth from 'next-auth'
import type { EmailConfig } from 'next-auth/providers'

const Postal: EmailConfig = {
  id: 'postal',
  type: 'email',
  name: 'Email',
  from: 'Acme Store <[email protected]>',
  maxAge: 24 * 60 * 60,
  options: {},
  async sendVerificationRequest({ identifier, url, provider }) {
    const response = await fetch('https://api.postal.so/emails', {
      method: 'POST',
      headers: { Authorization: `Bearer ${process.env.POSTAL_API_KEY}`, 'Content-Type': 'application/json' },
      body: JSON.stringify({
        from: provider.from,
        to: [identifier],
        subject: 'Your sign-in link',
        html: `<p><a href="${url}">Sign in</a></p><p>The link is valid for 24 hours.</p>`,
        text: `Sign in with this link: ${url}`,
      }),
    })

    if (!response.ok) {
      throw new Error(`Postal responded with ${response.status}`)
    }
  },
}

export const { handlers, auth, signIn, signOut } = NextAuth({
  // Email sign-in needs a database adapter (Prisma, Drizzle...).
  // adapter: PrismaAdapter(prisma),
  providers: [Postal],
})

The verification links are stored by the adapter. To use a Postal template, replace html and text with template: { id, variables: { URL: url } }.