Use maxclicks in v0
Connect the app you build in v0 to customer data and prepared campaigns in maxclicks. In a Next.js project, make API requests from server code such as a Route Handler or Server Action.
The API authenticates with a workspace key. Keep it in server-side environment variables and make requests from a Route Handler or Server Action. Never expose it to the browser.
Start with the HTTP request below to verify your workspace, then install the Node SDK for typed API calls in your application.
Make a first request over HTTP
This request runs in server-side JavaScript and needs no maxclicks package. Set MAXCLICKS_API_KEY in your server's secret store, then confirm the returned space before making a write.
const apiKey = process.env.MAXCLICKS_API_KEY
if (!apiKey) throw new Error('Set MAXCLICKS_API_KEY first')
const response = await fetch('https://api.maxclicks.ai/v1/me', {
headers: { Authorization: `Bearer ${apiKey}` },
})
const result = await response.json()
if (!response.ok) throw new Error(result.error?.message ?? 'Request failed')
console.log(result.data.space)
For a runtime without process.env, use its server-side secret API. Keep the key out of browser bundles. Follow the API quickstart to sync a contact and send a prepared template.
The examples below use the Node SDK, which provides types, pagination helpers, and typed errors.
Connect
Install the SDK
Requires Node.js 18 or newer. Install the SDK in your project:
npm install maxclicksSet the API key
Add
MAXCLICKS_API_KEYto your v0 project's environment variables. Create the key in maxclicks under Settings, Developers, API keys. It looks likemax_....MAXCLICKS_API_KEY=max_...Call the API from server code
Construct the client once. With no arguments it reads
MAXCLICKS_API_KEYand useshttps://api.maxclicks.ai/v1.import { Maxclicks } from 'maxclicks' const mc = new Maxclicks() // reads MAXCLICKS_API_KEY
Server Action
Use a Server Action to write from a form. This runs on the server, so the key stays private.
'use server'
import { Maxclicks } from 'maxclicks'
const mc = new Maxclicks()
export async function subscribe(email: string, firstName: string) {
return mc.records.upsert('students', { email, firstName, tags: ['beta'] })
}
upsert matches on contact identity (userId first, then email, then phone), so submitting the same person twice updates one contact instead of creating a second.
Route Handler
Use a Route Handler when v0 code, or an external caller, posts JSON to an endpoint.
import { Maxclicks } from 'maxclicks'
const mc = new Maxclicks()
export async function POST(request: Request) {
const { email, firstName } = await request.json()
const contact = await mc.records.upsert('students', { email, firstName })
return Response.json(contact)
}
Common calls
The first argument is a schema id or slug. Records are flat: base fields plus your own attribute values, all at the top level.
await mc.me() // current key and space
await mc.records.upsert('students', { email }) // create or update a contact
await mc.events.fire('purchase-completed', { eventId: 'ord_123', amount: 42 })
await mc.templates.send(templateId, { data: { contact: { email } } })
await mc.workflows.trigger('7Qk2ZbN4x9LmR3vTpW8sHc0F', { orderId: 'A-1024' })
await mc.forms.submit(formId, { contact: { email } })
Every list returns a Page that is both one page and an async iterable over all pages.
for await (const record of await mc.records.list('students')) {
console.log(record.id)
}
Errors
On success a call returns the data directly. On failure it throws a typed error, one of the MaxclicksError subclasses.
| Error | When |
|---|---|
MaxclicksBadRequestError | 400 validation failure |
MaxclicksAuthenticationError | 401 missing or invalid API key |
MaxclicksPermissionError | 403 insufficient permission |
MaxclicksNotFoundError | 404 resource not found |
MaxclicksConflictError | 409 identifier or uniqueness conflict |
MaxclicksRateLimitError | 429 rate limited (carries retryAfterMs) |
MaxclicksServerError | 5xx server error |
The SDK retries 429 within its budget. It retries 5xx and transport errors only for reads and writes carrying an idempotency key. Preserve the key and payload while reconciling an uncertain result.
import { Maxclicks, MaxclicksConflictError } from 'maxclicks'
const mc = new Maxclicks()
try {
await mc.records.create('students', { email: '[email protected]' })
} catch (error) {
if (error instanceof MaxclicksConflictError) {
// identity already exists; use upsert instead
}
}
The API key inherits its owner's workspace permissions. Store it only in server environment variables. Keys are issued and revoked in maxclicks under Settings, Developers, API keys, not over the API. If a key leaks, revoke it there and issue a new one.