API Conventions
Use this page as the baseline contract for direct HTTP integrations. Endpoint pages document endpoint-specific fields, limits, and examples.
Base URL
All REST API endpoints use this base URL:
https://app.bentonow.com/api/v1
Endpoint pages show paths relative to /api/v1. For example, /batch/events becomes:
https://app.bentonow.com/api/v1/batch/events
Authentication
Bento uses HTTP Basic authentication. Use your publishable key as the username and your secret key as the password.
Authorization: Basic BASE64(publishable_key:secret_key)
Every API request must also include site_uuid as a query parameter so Bento knows which site to use.
https://app.bentonow.com/api/v1/fetch/tags?site_uuid=YOUR_SITE_UUID
Read the full Authentication page if you need key locations, encoding examples, or security guidance.
Required Headers
Every request should include these headers:
| Header | Required | Notes |
|---|---|---|
Authorization | Yes | Basic auth credentials. |
User-Agent | Yes | Use a real app name, such as AcmeCRM/1.0. Requests without one may be blocked before they reach the API. |
Content-Type | For JSON bodies | Use application/json for POST, PUT, and PATCH requests. |
User-Agent first. Missing or generic user agents are the most common cause.Request Shape
POST endpoints accept JSON request bodies. Batch endpoints usually wrap records in a plural top-level key:
| Endpoint | Top-level key | Typical batch size |
|---|---|---|
/batch/events | events | 1 to 1000 events |
/batch/subscribers | subscribers | 1 to 1000 subscribers |
/batch/emails | emails | 1 to 60 emails |
Use UTF-8 JSON, avoid sending secrets in event details or custom fields, and keep field names lowercase and underscored where possible.
Response Codes
| Status | Meaning | What to do |
|---|---|---|
200 or 201 | Request accepted or completed. | Continue. |
400 | Invalid request body or parameters. | Check required fields and data types. |
401 | Missing or invalid auth, or missing site_uuid. | Check credentials and query string. |
403 | Request blocked or account access issue. | Check User-Agent, account status, and support guidance. |
404 | Endpoint or resource not found. | Check path, method, and identifiers. |
429 | Rate limited. | Slow down and retry with backoff. |
5xx | Bento or upstream infrastructure error. | Retry later with backoff. |
For field-level guidance, use the Errors Reference.
Pagination
List-style endpoints use endpoint-specific pagination. Many older endpoints accept a page value. When an endpoint documents a page parameter, start at 1 and request the next page only after the previous response succeeds.
Do not poll broad list endpoints when a webhook, event trigger, or batch export would solve the same problem.
Rate Limits And Retries
Rate limits vary by endpoint and account history. Endpoint pages call out important limits, such as the transactional email send pace.
Use these defaults unless a page says otherwise:
- Batch writes: prefer batches over many single-record requests.
- Retries: retry
429and5xxwith exponential backoff. - Timeouts: set an application timeout and log the request body shape without logging secrets.
- Idempotency: avoid blindly retrying email sends from user-facing actions unless your application can prevent duplicates.
Versioning
The current public REST namespace is /api/v1. Bento keeps backwards compatibility where possible and documents meaningful API behavior changes in the API Changelog.
Examples
cURL
curl -X POST 'https://app.bentonow.com/api/v1/batch/events?site_uuid=YOUR_SITE_UUID' \
-H 'Authorization: Basic YOUR_BASE64_CREDENTIALS' \
-H 'User-Agent: AcmeCRM/1.0' \
-H 'Content-Type: application/json' \
-d '{
"events": [{
"type": "$signed_up",
"email": "person@example.com",
"fields": { "first_name": "Ari" }
}]
}'
Node.js
const credentials = Buffer.from(`${process.env.BENTO_PUBLISHABLE_KEY}:${process.env.BENTO_SECRET_KEY}`).toString('base64')
await fetch(`https://app.bentonow.com/api/v1/batch/events?site_uuid=${process.env.BENTO_SITE_UUID}`, {
method: 'POST',
headers: {
Authorization: `Basic ${credentials}`,
'User-Agent': 'AcmeCRM/1.0',
'Content-Type': 'application/json',
},
body: JSON.stringify({
events: [{ type: '$signed_up', email: 'person@example.com' }],
}),
})
Python
import base64
import os
import requests
credentials = base64.b64encode(
f"{os.environ['BENTO_PUBLISHABLE_KEY']}:{os.environ['BENTO_SECRET_KEY']}".encode()
).decode()
requests.post(
f"https://app.bentonow.com/api/v1/batch/events?site_uuid={os.environ['BENTO_SITE_UUID']}",
headers={
"Authorization": f"Basic {credentials}",
"User-Agent": "AcmeCRM/1.0",
"Content-Type": "application/json",
},
json={"events": [{"type": "$signed_up", "email": "person@example.com"}]},
)
