Create a write key
Generate it in API keys. Secret-key requests activate only with a current paid workspace plan.
Developer reference
Grounded documentation for every endpoint currently implemented by the AudienceRelay v1 collector API.
https://audiencerelay.com/api/v1Formatapplication/jsonVersionv1API surface
The API creates and reads form resources, accepts public submissions, and retrieves collected data. Workspace configuration remains in the dashboard.
| Method | Path | Access | Result |
|---|---|---|---|
GET | /forms | Read or write key | Paginated form collection. |
POST | /forms | Write key | Create one draft form. |
POST | /forms/bulk | Write key | Create 1–50 draft forms atomically. |
GET | /products/{product}/forms | Read or write key | Paginated product collection. |
POST | /products/{product}/forms | Write key | Create a product-specific draft form. |
GET | /forms/{form_id} | Read or write key | Form detail with ordered fields. |
POST | /forms/{public_token}/submissions | Publishable token | Create one submission. |
GET | /forms/{form_id}/submissions | Read or write key | Page through submissions. |
GET | /forms/{form_id}/submissions/{submission_id} | Read or write key | Single submission detail. |
GET | /submission-files/{download_token} | Read or write key | Download one private submitted file. |
Generate it in API keys. Secret-key requests activate only with a current paid workspace plan.
Create through the API, then manage fields, protections, webhooks, and activation in the dashboard.
Submit with the publishable token and retrieve privately with a secret key.
Authentication
Publishable tokens collect responses. Secret keys manage and retrieve workspace resources from trusted servers.
POST /api/v1/forms/PUBLISHABLE_TOKEN/submissionsThe token identifies one form and is safe in browser code. It cannot list forms, retrieve submissions, or access another form.
Authorization: Bearer ar_live_YOUR_SECRET_KEYKeys are shown once and stored as hashes. Read keys can use GET endpoints. Write keys can also create forms. Revoked, unpaid, expired-plan, and inactive-workspace keys return 401.
| Operation | Publishable token | Read key | Write key |
|---|---|---|---|
| Submit to its active form | Yes | No | No |
| List/read forms | No | Yes | Yes |
| Read submissions | No | Yes | Yes |
| Create forms | No | No | Yes |
| Edit, publish, or delete forms | No | No | No API endpoint |
Dynamic forms API
Create and list dynamic forms with the product endpoint, then use the shared form and submission endpoints for detail and collected data.
| Method | Endpoint | Authentication | Purpose |
|---|---|---|---|
GET | /products/custom-forms/forms | Paid secret key | List only dynamic forms. |
POST | /products/custom-forms/forms | Paid write key | Create one draft dynamic forms. |
GET | /forms/{form_id} | Paid secret key | Read form configuration and fields. |
POST | /forms/{public_token}/submissions | Publishable token | Collect one response from an active form. |
GET | /forms/{form_id}/submissions | Paid secret key | Page through collected responses. |
GET | /forms/{form_id}/submissions/{submission_id} | Paid secret key | Retrieve one response. |
GET
curl "https://audiencerelay.com/api/v1/products/custom-forms/forms?page=1&page_size=20" \
-H "Authorization: Bearer ar_live_YOUR_SECRET_KEY"{
"data": [{
"id": 42,
"name": "Example Dynamic forms",
"slug": "example-custom-a1b2c3",
"type": "custom",
"status": "draft",
"public_token": "PUBLISHABLE_TOKEN",
"allowed_origins": ["https://example.com"],
"submission_count": 0,
"created_at": "2026-08-15T12:30:00+00:00",
"updated_at": "2026-08-15T12:30:00+00:00"
}],
"product": "custom-forms",
"pagination": {
"page": 1, "page_size": 20, "total": 1,
"total_pages": 1, "has_previous": false, "has_next": false
}
}POST
curl -X POST "https://audiencerelay.com/api/v1/products/custom-forms/forms" \
-H "Authorization: Bearer ar_live_YOUR_WRITE_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Example Dynamic forms",
"allowed_origins": ["https://example.com"]
}'The product endpoint fixes type to custom. The response is 201 with a serialized draft form in data.
POST
curl -X POST "https://audiencerelay.com/api/v1/forms/PUBLISHABLE_TOKEN/submissions" \
-H "Content-Type: application/json" \
-d '{
"email": "person@example.com"
}'{
"id": 184,
"created_at": "2026-08-15T12:45:00+00:00"
}No secret key is sent to this endpoint. The form must be active. Browser requests with an Origin header must match the form allowlist.
GET
curl "https://audiencerelay.com/api/v1/forms/FORM_ID" \
-H "Authorization: Bearer ar_live_YOUR_SECRET_KEY"The data.fields array returns each field’s id, key, label, type, required, position, and select options. Build payloads from these keys instead of assuming the form has never been customized.
GET
curl "https://audiencerelay.com/api/v1/forms/FORM_ID/submissions?page=1&page_size=50" \
-H "Authorization: Bearer ar_live_YOUR_SECRET_KEY"
curl "https://audiencerelay.com/api/v1/forms/FORM_ID/submissions/SUBMISSION_ID" \
-H "Authorization: Bearer ar_live_YOUR_SECRET_KEY"Collection results include data, email, marketing_consent, and created_at. Single-response detail also includes source_origin.
API-created forms start in draft. Field editing, form activation, notification settings, webhook settings, and deletion are dashboard operations in this API version. There is no undocumented PATCH or DELETE endpoint.
Waitlists API
Create and list waitlists with the product endpoint, then use the shared form and submission endpoints for detail and collected data.
| Method | Endpoint | Authentication | Purpose |
|---|---|---|---|
GET | /products/waitlists/forms | Paid secret key | List only waitlists. |
POST | /products/waitlists/forms | Paid write key | Create one draft waitlists. |
GET | /forms/{form_id} | Paid secret key | Read form configuration and fields. |
POST | /forms/{public_token}/submissions | Publishable token | Collect one response from an active form. |
GET | /forms/{form_id}/submissions | Paid secret key | Page through collected responses. |
GET | /forms/{form_id}/submissions/{submission_id} | Paid secret key | Retrieve one response. |
GET
curl "https://audiencerelay.com/api/v1/products/waitlists/forms?page=1&page_size=20" \
-H "Authorization: Bearer ar_live_YOUR_SECRET_KEY"{
"data": [{
"id": 42,
"name": "Example Waitlists",
"slug": "example-waitlist-a1b2c3",
"type": "waitlist",
"status": "draft",
"public_token": "PUBLISHABLE_TOKEN",
"allowed_origins": ["https://example.com"],
"submission_count": 0,
"created_at": "2026-08-15T12:30:00+00:00",
"updated_at": "2026-08-15T12:30:00+00:00"
}],
"product": "waitlists",
"pagination": {
"page": 1, "page_size": 20, "total": 1,
"total_pages": 1, "has_previous": false, "has_next": false
}
}POST
curl -X POST "https://audiencerelay.com/api/v1/products/waitlists/forms" \
-H "Authorization: Bearer ar_live_YOUR_WRITE_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Example Waitlists",
"allowed_origins": ["https://example.com"]
}'The product endpoint fixes type to waitlist. The response is 201 with a serialized draft form in data.
POST
curl -X POST "https://audiencerelay.com/api/v1/forms/PUBLISHABLE_TOKEN/submissions" \
-H "Content-Type: application/json" \
-d '{
"name": "Ada Lovelace",
"email": "ada@example.com",
"marketing_consent": true
}'{
"id": 184,
"created_at": "2026-08-15T12:45:00+00:00"
}No secret key is sent to this endpoint. The form must be active. Browser requests with an Origin header must match the form allowlist.
GET
curl "https://audiencerelay.com/api/v1/forms/FORM_ID" \
-H "Authorization: Bearer ar_live_YOUR_SECRET_KEY"The data.fields array returns each field’s id, key, label, type, required, position, and select options. Build payloads from these keys instead of assuming the form has never been customized.
GET
curl "https://audiencerelay.com/api/v1/forms/FORM_ID/submissions?page=1&page_size=50" \
-H "Authorization: Bearer ar_live_YOUR_SECRET_KEY"
curl "https://audiencerelay.com/api/v1/forms/FORM_ID/submissions/SUBMISSION_ID" \
-H "Authorization: Bearer ar_live_YOUR_SECRET_KEY"Collection results include data, email, marketing_consent, and created_at. Single-response detail also includes source_origin.
API-created forms start in draft. Field editing, form activation, notification settings, webhook settings, and deletion are dashboard operations in this API version. There is no undocumented PATCH or DELETE endpoint.
Newsletters API
Create and list newsletters with the product endpoint, then use the shared form and submission endpoints for detail and collected data.
| Method | Endpoint | Authentication | Purpose |
|---|---|---|---|
GET | /products/newsletters/forms | Paid secret key | List only newsletters. |
POST | /products/newsletters/forms | Paid write key | Create one draft newsletters. |
GET | /forms/{form_id} | Paid secret key | Read form configuration and fields. |
POST | /forms/{public_token}/submissions | Publishable token | Collect one response from an active form. |
GET | /forms/{form_id}/submissions | Paid secret key | Page through collected responses. |
GET | /forms/{form_id}/submissions/{submission_id} | Paid secret key | Retrieve one response. |
GET
curl "https://audiencerelay.com/api/v1/products/newsletters/forms?page=1&page_size=20" \
-H "Authorization: Bearer ar_live_YOUR_SECRET_KEY"{
"data": [{
"id": 42,
"name": "Example Newsletters",
"slug": "example-newsletter-a1b2c3",
"type": "newsletter",
"status": "draft",
"public_token": "PUBLISHABLE_TOKEN",
"allowed_origins": ["https://example.com"],
"submission_count": 0,
"created_at": "2026-08-15T12:30:00+00:00",
"updated_at": "2026-08-15T12:30:00+00:00"
}],
"product": "newsletters",
"pagination": {
"page": 1, "page_size": 20, "total": 1,
"total_pages": 1, "has_previous": false, "has_next": false
}
}POST
curl -X POST "https://audiencerelay.com/api/v1/products/newsletters/forms" \
-H "Authorization: Bearer ar_live_YOUR_WRITE_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Example Newsletters",
"allowed_origins": ["https://example.com"]
}'The product endpoint fixes type to newsletter. The response is 201 with a serialized draft form in data.
POST
curl -X POST "https://audiencerelay.com/api/v1/forms/PUBLISHABLE_TOKEN/submissions" \
-H "Content-Type: application/json" \
-d '{
"email": "reader@example.com",
"marketing_consent": true
}'{
"id": 184,
"created_at": "2026-08-15T12:45:00+00:00"
}No secret key is sent to this endpoint. The form must be active. Browser requests with an Origin header must match the form allowlist.
GET
curl "https://audiencerelay.com/api/v1/forms/FORM_ID" \
-H "Authorization: Bearer ar_live_YOUR_SECRET_KEY"The data.fields array returns each field’s id, key, label, type, required, position, and select options. Build payloads from these keys instead of assuming the form has never been customized.
GET
curl "https://audiencerelay.com/api/v1/forms/FORM_ID/submissions?page=1&page_size=50" \
-H "Authorization: Bearer ar_live_YOUR_SECRET_KEY"
curl "https://audiencerelay.com/api/v1/forms/FORM_ID/submissions/SUBMISSION_ID" \
-H "Authorization: Bearer ar_live_YOUR_SECRET_KEY"Collection results include data, email, marketing_consent, and created_at. Single-response detail also includes source_origin.
API-created forms start in draft. Field editing, form activation, notification settings, webhook settings, and deletion are dashboard operations in this API version. There is no undocumented PATCH or DELETE endpoint.
This API collects consent and subscriber data. It does not send bulk email campaigns. Use authenticated submission retrieval or a signed webhook to pass consented records to an email platform.
Contact forms API
Create and list contact forms with the product endpoint, then use the shared form and submission endpoints for detail and collected data.
| Method | Endpoint | Authentication | Purpose |
|---|---|---|---|
GET | /products/contact-forms/forms | Paid secret key | List only contact forms. |
POST | /products/contact-forms/forms | Paid write key | Create one draft contact forms. |
GET | /forms/{form_id} | Paid secret key | Read form configuration and fields. |
POST | /forms/{public_token}/submissions | Publishable token | Collect one response from an active form. |
GET | /forms/{form_id}/submissions | Paid secret key | Page through collected responses. |
GET | /forms/{form_id}/submissions/{submission_id} | Paid secret key | Retrieve one response. |
GET
curl "https://audiencerelay.com/api/v1/products/contact-forms/forms?page=1&page_size=20" \
-H "Authorization: Bearer ar_live_YOUR_SECRET_KEY"{
"data": [{
"id": 42,
"name": "Example Contact forms",
"slug": "example-contact-a1b2c3",
"type": "contact",
"status": "draft",
"public_token": "PUBLISHABLE_TOKEN",
"allowed_origins": ["https://example.com"],
"submission_count": 0,
"created_at": "2026-08-15T12:30:00+00:00",
"updated_at": "2026-08-15T12:30:00+00:00"
}],
"product": "contact-forms",
"pagination": {
"page": 1, "page_size": 20, "total": 1,
"total_pages": 1, "has_previous": false, "has_next": false
}
}POST
curl -X POST "https://audiencerelay.com/api/v1/products/contact-forms/forms" \
-H "Authorization: Bearer ar_live_YOUR_WRITE_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Example Contact forms",
"allowed_origins": ["https://example.com"]
}'The product endpoint fixes type to contact. The response is 201 with a serialized draft form in data.
POST
curl -X POST "https://audiencerelay.com/api/v1/forms/PUBLISHABLE_TOKEN/submissions" \
-H "Content-Type: application/json" \
-d '{
"name": "Ayo",
"email": "ayo@example.com",
"message": "I would like to discuss a partnership."
}'{
"id": 184,
"created_at": "2026-08-15T12:45:00+00:00"
}No secret key is sent to this endpoint. The form must be active. Browser requests with an Origin header must match the form allowlist.
GET
curl "https://audiencerelay.com/api/v1/forms/FORM_ID" \
-H "Authorization: Bearer ar_live_YOUR_SECRET_KEY"The data.fields array returns each field’s id, key, label, type, required, position, and select options. Build payloads from these keys instead of assuming the form has never been customized.
GET
curl "https://audiencerelay.com/api/v1/forms/FORM_ID/submissions?page=1&page_size=50" \
-H "Authorization: Bearer ar_live_YOUR_SECRET_KEY"
curl "https://audiencerelay.com/api/v1/forms/FORM_ID/submissions/SUBMISSION_ID" \
-H "Authorization: Bearer ar_live_YOUR_SECRET_KEY"Collection results include data, email, marketing_consent, and created_at. Single-response detail also includes source_origin.
API-created forms start in draft. Field editing, form activation, notification settings, webhook settings, and deletion are dashboard operations in this API version. There is no undocumented PATCH or DELETE endpoint.
All forms
Use these endpoints when an integration works across multiple AudienceRelay products.
GET
curl "https://audiencerelay.com/api/v1/forms?page=1&page_size=25&form_type=waitlist" \
-H "Authorization: Bearer ar_live_YOUR_SECRET_KEY"page starts at 1, page_size is clamped to 1–100, and form_type accepts waitlist, newsletter, contact, or custom. Omit the filter for every type.
POST
curl -X POST "https://audiencerelay.com/api/v1/forms" \
-H "Authorization: Bearer ar_live_YOUR_WRITE_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Partner enquiries",
"type": "contact",
"allowed_origins": ["https://example.com"]
}'A 201 response returns {"data": FORM}. Unlike the product-specific create response, this response also includes the generated default fields.
POST
curl -X POST "https://audiencerelay.com/api/v1/forms/bulk" \
-H "Authorization: Bearer ar_live_YOUR_WRITE_KEY" \
-H "Content-Type: application/json" \
-d '{"forms":[
{"name":"Lagos launch", "type":"waitlist", "allowed_origins":[]},
{"name":"General enquiries", "type":"contact", "allowed_origins":["https://example.com"]}
]}'{
"data": [FORM, FORM],
"created": 2
}The complete transaction succeeds or fails together. Bulk response forms do not include field arrays; retrieve each form to read its generated fields.
| Property | Type | Notes |
|---|---|---|
id | integer | Workspace-scoped form identifier. |
name, slug | string | Display name and generated unique slug. |
type | string | One of the four supported form types. |
status | string | New API-created forms are draft. |
public_token | string | Used only for hosted/public submission. |
allowed_origins | string[] | Normalized HTTP(S) browser origins. |
submission_count | integer | Included in collection responses. |
fields | object[] | Included in form detail and global single-create response. |
created_at, updated_at | string | UTC ISO-8601 timestamps. |
Submissions
The API supports page-number pagination for dashboards and cursor pagination for incremental processing.
POST
fetch("https://audiencerelay.com/api/v1/forms/PUBLISHABLE_TOKEN/submissions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": "checkout-lead-0184"
},
body: JSON.stringify({
email: "person@example.com",
marketing_consent: true
})
});Send one JSON object. Known field values are normalized and limited to 5,000 characters; unknown keys are ignored. Required fields, emails, dates, ratings, dropdowns, multiple-choice answers, and checkbox arrays are validated. Section headings are never stored as response fields.
Idempotency-Key is optional but recommended. Repeating the same key for the same form returns the original submission with HTTP 200 and "duplicate": true; the first accepted request returns HTTP 201.
const body = new FormData();
body.append("email", "person@example.com");
body.append("documents", fileInput.files[0]);
fetch("https://audiencerelay.com/api/v1/forms/PUBLISHABLE_TOKEN/submissions", {
method: "POST",
headers: { "Idempotency-Key": "application-0184" },
body
});File fields are available on waitlist, contact, and custom forms. A response may include up to five JPG, PNG, GIF, WebP, PDF, DOC, or DOCX files, each no larger than 10 MB. Do not set the multipart Content-Type header manually; the browser adds its boundary.
GET
GET /api/v1/forms/FORM_ID/submissions?page=3&page_size=50The response includes pagination and a compatibility next_cursor. Page size is clamped to 1–100.
GET
GET /api/v1/forms/FORM_ID/submissions?limit=50&cursor=184Results are newest first. Supplying cursor omits page metadata. Continue with the returned next_cursor until it is null.
{
"data": [{
"id": 184,
"data": {"email": "person@example.com"},
"email": "person@example.com",
"marketing_consent": true,
"created_at": "2026-08-15T12:45:00+00:00"
}],
"next_cursor": null,
"pagination": {
"page": 1, "page_size": 50, "total": 1,
"total_pages": 1, "has_previous": false, "has_next": false
}
}GET
curl "https://audiencerelay.com/api/v1/forms/FORM_ID/submissions/SUBMISSION_ID" \
-H "Authorization: Bearer ar_live_YOUR_SECRET_KEY"Returns {"data": SUBMISSION}. The detail shape adds source_origin. The form and submission must both belong to the key’s workspace.
curl -OJ "https://audiencerelay.com/submission-files/DOWNLOAD_TOKEN" \
-H "Authorization: Bearer ar_live_YOUR_SECRET_KEY"File metadata in submission data includes a relative download_url. The key must belong to the same workspace and have active paid API access. Signed-in workspace members can use the same URL in the response inbox.
Operations
Webhook configuration is performed per form in the dashboard; this section documents the event contract the backend sends.
POST https://your-domain.example/webhooks/audience-relay
Content-Type: application/json
X-AudienceRelay-Event: submission.created
X-AudienceRelay-Signature: sha256=HEX_HMAC
{
"event": "submission.created",
"delivery_id": 91,
"submission": {
"id": 184,
"form_id": 42,
"form_name": "Partner enquiries",
"data": {"email": "person@example.com"},
"email": "person@example.com",
"marketing_consent": true,
"created_at": "2026-08-15T12:45:00+00:00"
}
}Compute HMAC-SHA256 over the exact raw body using the configured form secret, prefix the lowercase hexadecimal digest with sha256=, and compare it with a timing-safe function. AudienceRelay tries failed delivery up to three times.
Browser preflight supports POST, OPTIONS, the Content-Type header, and a 600-second preflight cache. Allowed origins receive CORS headers on success and error responses.
| Status | Grounded causes |
|---|---|
400 | Invalid JSON, unsupported form type, invalid form values, required field, email, select option, or bulk size. |
401 | Secret key is absent, invalid, revoked, unpaid, expired, or attached to an inactive workspace. |
403 | Read-only key used for creation, disallowed browser origin, inactive public form, or honeypot rejection. |
404 | Product, form, or submission is missing or outside the key’s workspace. |
413 | Public submission exceeds the form’s configured payload limit. |
422 | Framework-level request or parameter shape validation failed. |
429 | Public submission exceeded the form’s per-source rate limit. |
{"error":"Human-readable explanation."}