API quickstart
Connect your application to the customer experience your team has built in maxclicks. This guide verifies your API key, saves a contact, and sends a prepared email. The examples use cURL so you can inspect each request and response directly.
Prerequisites
For the first read request, you need a maxclicks space and an API key. To save a contact, create a contact schema in the app. To send the email, also prepare:
| Requirement | What to check |
|---|---|
| Brand and sender | Your brand details and sender are configured in the space. |
| Verified sending domain | The DNS records have been added and the domain is verified. |
| A sendable template | The template has a sender, renders in preview, and uses your contact schema. |
| A test recipient | Use an address you control, with the consent required for the template. |
Your team builds schemas, content, and journeys in the app. Your integration supplies customer data and triggers the prepared experience. You can complete the first three steps before setting up email delivery.
Step 1: Create an API key
Open your space, then Settings → Developers → API keys. Create a key for this integration and save the full value in your secret manager. The value is shown once.
For these examples, set the key in your local environment:
export MAXCLICKS_API_KEY='YOUR_API_KEY'
The key inherits its owner's permissions in the space. Keep it in server code and local development tools; never ship it to a browser or commit it to your repository. See authentication for permissions and key rotation.
Step 2: Authenticate
Call GET /v1/me. This checks the credential without changing customer data.
curl --fail-with-body https://api.maxclicks.ai/v1/me \
-H "Authorization: Bearer $MAXCLICKS_API_KEY"
A successful response returns data.apiKey, data.user, data.space, and data.role. Check that data.space identifies the workspace you intend to use. A valid key without a space binding returns space: null; see space resolution before proceeding.
Successful REST responses wrap their result in data. Errors use error.
Check the HTTP status first, then the documented result fields. List responses
also include pagination.
Step 3: Upsert a record
Find the contact schema you created in the app:
curl --fail-with-body https://api.maxclicks.ai/v1/schemas \
-H "Authorization: Bearer $MAXCLICKS_API_KEY"
Copy its slug into MAXCLICKS_SCHEMA. Use GET /v1/schemas/{schema}/attributes to inspect the fields it accepts. Include required writable custom fields without defaults. Evaluated fields and fields with definition.valueSource are not caller-writable. A schema with writable AI auto-fill requires available credits on create/upsert. The example below sends the built-in contact email field; replace the address with one you control.
export MAXCLICKS_SCHEMA='YOUR_CONTACT_SCHEMA_SLUG'
curl --fail-with-body -X POST \
"https://api.maxclicks.ai/v1/schemas/$MAXCLICKS_SCHEMA/records/upsert" \
-H "Authorization: Bearer $MAXCLICKS_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: quickstart-contact-001" \
-d '{ "email": "[email protected]" }'
An upsert creates or updates a contact. An explicit id selects that record or fails with 404. Without it, maxclicks matches userId first; an email matches only a contact without userId, and a phone matches only a contact without userId or email. Use one durable identity strategy across your product and email sends. Save the returned record ID unchanged and inspect any warnings.
Use the same idempotency key and body when retrying this request. Choose a new key for a different contact or a later update. A strict create, POST /v1/schemas/{schema}/records, returns 409 identifier_conflict if that identity already exists.
Step 4: Find the template
Prepare and preview your email in Templates, then list the templates available to your space:
curl --fail-with-body https://api.maxclicks.ai/v1/templates \
-H "Authorization: Bearer $MAXCLICKS_API_KEY"
Copy the template ID into MAXCLICKS_TEMPLATE_ID and retrieve its requirements:
export MAXCLICKS_TEMPLATE_ID='YOUR_TEMPLATE_ID'
curl --fail-with-body \
"https://api.maxclicks.ai/v1/templates/$MAXCLICKS_TEMPLATE_ID" \
-H "Authorization: Bearer $MAXCLICKS_API_KEY"
Read expectedDataRepresentation to find the keys and schemas the template expects. The next example assumes a contact key named contact; use the actual key from your template and include any other required data.
Step 5: Send it
This request sends an email to the recipient in your payload. Use your test address and a template you have reviewed.
curl --fail-with-body -X POST \
"https://api.maxclicks.ai/v1/templates/$MAXCLICKS_TEMPLATE_ID/send" \
-H "Authorization: Bearer $MAXCLICKS_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: quickstart-template-send-001" \
-d '{ "data": { "contact": { "email": "[email protected]" } } }'
The data object supplies the template's customer context. Records in that context are written before rendering, so pass the same contact identity you used above. You can also pass the saved record id inside the corresponding contact object. The API sends the stored template content; it does not accept a replacement subject or body.
Inspect the result as well as the HTTP status. templates.send returns data.emailId, data.status, and data.error. A 200 response with status: "failed" does not establish whether another send is safe: the public result combines rejection, cancellation, retryable refusal, and uncertain provider outcomes. Keep emailId and your original key, and reconcile the send in the app before creating another operation. status: "sent" means the provider accepted the send; it is not a guarantee of inbox delivery.
Marketing sends require the contact's email consent and, when the template
uses a topic, their subscription to that topic. Suppression checks also apply.
If the API returns recipient_not_subscribed or recipient_suppressed,
resolve the recipient's eligibility before sending again.
Before you connect production traffic
- Persist an idempotency key per supported logical write. After a timeout, keep the original key and payload; reconcile any unresolved outcome.
- Handle errors, including
200responses with an operation-level failure. - Pace workers within rate limits, and parse both supported
Retry-Afterformats. - Follow pagination when a result spans more than one page.