Send from a client · Published 2026-09-22 · Updated 2026-09-29 · AgentiSend
Send email from a v0 app
To send email from a v0 app, verify a domain, create a key with a budget, store it as a project secret, and ask v0 to add a server-side send.
To send email from a v0 app, verify a domain, create a key with sending_access and a budget, store it as a project secret, and ask v0 to add a server-side send that calls the API. v0 has no AgentiSend connector, and this page does not describe one. v0 produces a Next.js app, so the send belongs in a Server Action or a route handler. A component that calls the API from the browser would publish the key.
A form that posts to the server
When the send starts from a form, a Server Action lets the form post straight to server code with no route in between. The sample below is that action. If the page already calls an API route, the route handler on the Next.js guide does the same send.
Set up the key
- Verify the domain the mail will come from.
- Create a key with
POST /api-keysand permissionsending_access, then cap it withPATCH /limits/keys/{id}. - Add
AGENTISEND_API_KEYandMAIL_FROMas project secrets. The action reads both as server environment variables; no client component should import either.
The prompt to paste
Add a Server Action in app/actions.ts that sends an email through AgentiSend when the form on this page is submitted. Match the Server Action sample at https://agentisend.com/docs/guides/nextjs, with 'use server' as the first line of the file. Install the npm package agentisend and read https://agentisend.com/openapi.json for the contract. There is no native AgentiSend connector to enable. Read the key from the project secret AGENTISEND_API_KEY and the sender from MAIL_FROM. Derive the idempotency key from the recipient. Return the id on success, or code and fix on a refusal, show the fix under the form, and never retry when retryable is false.The code that prompt should produce
/**
* app/actions.ts — the same send as a Server Action, for a form that posts
* straight to the server with no route handler in between.
*
* `'use server'` belongs at the top of the real file; it is a comment here so
* that this directory typechecks without the Next.js compiler.
*/
// 'use server';
import { AgentiSend, AgentiSendError } from 'agentisend';
const agentisend = new AgentiSend();
function mailFrom(): string {
const from = process.env.MAIL_FROM;
if (!from) throw new Error('Set MAIL_FROM to an address on a domain you have verified.');
return from;
}
export interface InviteResult {
id?: string;
error?: { code: string; fix: string };
}
export async function inviteTeammate(formData: FormData): Promise<InviteResult> {
const email = String(formData.get('email') ?? '');
if (!email) return { error: { code: 'validation_error', fix: 'Fill in the email field.' } };
try {
const { id } = await agentisend.emails.send(
{
from: mailFrom(),
to: email,
subject: 'You have been invited',
text: 'Open the console to accept the invitation.',
},
{ idempotencyKey: `invite/${email}` },
);
return { id };
} catch (err) {
if (err instanceof AgentiSendError) return { error: { code: err.code, fix: err.fix } };
throw err;
}
}In the sample, 'use server' is a comment so the examples directory typechecks without the Next.js compiler. In the app it is the first line of app/actions.ts, uncommented. The file is run by the test suite against a local AgentiSend server.
Show the fix instead of a generic error
The action returns { id } when the send is accepted and { error: { code, fix } } when it is refused, so the form can print the fix text beside the field the person filled in. An empty email field never reaches the API. Keep the returned id: GET /emails/{id} says where that message is now, long after the form has gone.
The same limits from every client
Budgets, loop detection, approvals and the kill switch behave identically whichever client holds the key, so they are not repeated here. The guardrails checklist maps each item people are told to hand-write onto the request that already enforces it, and Email for AI agents names every control with its endpoint.
Next
- Email for AI agents names every control and the request that calls it.
- Email guardrails maps the usual checklist onto these same fields.
- Send email with Next.js is the guide this sample is taken from.