Quickstart
Install a client, make your first Bento API call, and wire up the three endpoints most teams rely on every day.
Last updated: October 30, 2025
Quickstart
This guide gets you production-ready with the Bento API. You will install an SDK (or use cURL), send your first request, and connect the three endpoints that cover 99% of customer data flows.
Note: Grab your publishable key, secret key, and Site UUID from Settings → API Keys in the Bento dashboard before calling the API.
Choose your client
We ship open-source libraries for the most common stacks. Each GitHub repository lists supported features and example code. Prefer to browse them all? See the SDK directory →
cURL
# cURL is most likely already installed on your machine
curl --version
JavaScript embed
<!-- Embed script for most websites -->
<script src="https://fast.bentonow.com?site_uuid={SITE_KEY}" async defer></script>
Laravel
# Install the Laravel SDK
composer require bentonow/bento-laravel-sdk
PHP
# Install the standalone PHP SDK
composer require bentonow/bento-php-sdk
Ruby
# Add to your application's Gemfile
gem 'bento-sdk', github: "bentonow/bento-ruby-sdk", branch: "master"
Next.js
# Install the Next.js SDK
npm install @bentonow/bento-nextjs-sdk --save
Node.js
# Install the Node.js SDK
npm install @bentonow/bento-node-sdk --save
If you run into questions, open an issue on the relevant GitHub repository—we review them quickly and credit helpful contributions.
Making your first API request
With credentials and a client ready, call the Tags endpoint to confirm access. These examples fetch every tag in your account.
GET /v1/fetch/tags
# cURL
curl -L -X GET 'https://app.bentonow.com/api/v1/fetch/tags?site_uuid=YourSITEUUID1234' \
-H 'Accept: application/json' \
-H 'Authorization: Basic [base64 of Publishable Key and Secret Key]'
<?php
// Laravel SDK
use Bentonow\BentoLaravel\BentoConnector;
use Bentonow\BentoLaravel\Requests\GetTags;
$bento = new BentoConnector();
$request = new GetTags();
$response = $bento->send($request);
return $response->json();
// Node.js SDK
bento.V1.Tags.getTags()
.then((result) => console.log(result))
.catch((error) => console.error(error));
Common setups and patterns
Most teams follow the same playbook: track events, sync subscribers, and occasionally send transactional emails. Each workflow hits one core endpoint.
Track user activity with POST /v1/batch/events
This single API call creates a user when necessary, records an event, updates custom fields, and can trigger automations.
Warning: Start with the handful of events you plan to automate on (e.g., sign up or purchase). Sending every interaction can create noise before you build flows.
cURL
curl -L -X POST 'https://app.bentonow.com/api/v1/batch/events?site_uuid=ExampleID1234' \
-H 'Content-Type: application/json' \
-H 'Authorization: Basic BASE64ENCODE(USERNAME+PASSWORD)' \
--data-raw '{
"events": [
{
"type": "account.signup",
"email": "test@test.com",
"fields": {
"first_name": "Jesse",
"last_name": "Pinkman"
}
}
]
}'
JavaScript (axios)
const axios = require("axios");
const data = JSON.stringify({
events: [
{
type: "account.signup",
email: "test@test.com",
fields: {
first_name: "Jesse",
last_name: "Pinkman",
},
},
],
});
const config = {
method: "post",
maxBodyLength: Infinity,
url: "https://app.bentonow.com/api/v1/batch/events?site_uuid=ExampleID1234",
headers: {
"Content-Type": "application/json",
Authorization: "Basic BASE64ENCODE(USERNAME+PASSWORD)",
},
data,
};
axios(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.error(error);
});
Node SDK
bento.V1.track({
email: "test@test.com",
type: "account.signup",
fields: {
first_name: "Jesse",
last_name: "Pinkman",
},
})
.then((result) => console.log(result))
.catch((error) => console.error(error));
Laravel SDK
<?php
use Bentonow\BentoLaravel\BentoConnector;
use Bentonow\BentoLaravel\Requests\CreateEvents;
use Bentonow\BentoLaravel\DataTransferObjects\EventData;
$bento = new BentoConnector();
$data = collect([
new EventData(
type: "account.signup",
email: "test@test.com",
fields: [
"first_name" => "Jesse",
"last_name" => "Pinkman",
]
),
]);
$request = new CreateEvents($data);
$response = $bento->send($request);
return $response->json();
Ruby on Rails
Bento::Events.track(
email: "test@test.com",
type: "$feature.used",
details: { feature_name: "KPI Dashboard" }
)
Sync subscribers with POST /v1/batch/subscribers
This endpoint mirrors the CSV importer. It never triggers automations, making it ideal for routine syncs from your CRM or data warehouse.
Note: The default behaviour does not modify subscription status. Pass the appropriate flags if you need to opt users in or out.
cURL
curl -L -X POST 'https://app.bentonow.com/api/v1/batch/subscribers?site_uuid=ExampleID1234' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Basic BASE64ENCODE(USERNAME+PASSWORD)' \
--data-raw '{
"subscribers": [
{
"email": "test@test.com",
"first_name": "John",
"last_name": "Doe",
"tags": "lead,mql",
"remove_tags": "customers",
"some_other_field": "some value"
}
]
}'
JavaScript (axios)
const axios = require("axios");
const data = JSON.stringify({
subscribers: [
{
email: "test@test.com",
first_name: "John",
last_name: "Doe",
tags: "lead,mql",
remove_tags: "customers",
some_other_field: "some value",
},
],
});
const config = {
method: "post",
maxBodyLength: Infinity,
url: "https://app.bentonow.com/api/v1/batch/subscribers?site_uuid=ExampleID1234",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
Authorization: "Basic BASE64ENCODE(USERNAME+PASSWORD)",
},
data,
};
axios(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.error(error);
});
Node SDK
bento.V1.Batch.importSubscribers({
subscribers: [
{
email: "test@bentonow.com",
age: 21,
},
{
email: "test2@bentonow.com",
some_custom_variable: "tester-123",
primary_user: true,
},
{
email: "test3@bentonow.com",
name: "Test User",
},
],
})
.then((result) => console.log(result))
.catch((error) => console.error(error));
Laravel SDK
<?php
use Bentonow\BentoLaravel\DataTransferObjects\ImportSubscribersData;
use Bentonow\BentoLaravel\BentoConnector;
use Bentonow\BentoLaravel\Requests\ImportSubscribers;
$bento = new BentoConnector();
$data = collect([
new ImportSubscribersData(
email: "test@test.com",
first_name: "John",
last_name: "Doe",
tags: ["lead", "mql"],
removeTags: ["customers"],
fields: ["role" => "ceo"]
),
]);
$request = new ImportSubscribers($data);
$response = $bento->send($request);
return $response->json();
Ruby on Rails
import = Bento::Subscribers.import([
{ email: "test@bentonow.com", first_name: "Jesse", last_name: "Hanley", widget_count: 1000 },
{ email: "test2@bentonow.com", first_name: "Jesse", last_name: "Hanley", company_name: "Tanuki Inc." },
{ email: "test3@bentonow.com", first_name: "Jesse", last_name: "Hanley", tags: "lead,new_subscriber", remove_tags: "customer" }
])
if import.failed?
raise StandardError, "Oh no! Something went wrong."
end
Send transactional email with POST /v1/batch/emails
Use this endpoint for time-sensitive messages (password resets, receipts, critical alerts). For slower flows, send an event and let an automation deliver the email so content stays editable inside Bento.
bento.V1.Batch.sendTransactionalEmails({
emails: [
{
to: "test@bentonow.com",
from: "jesse@bentonow.com",
subject: "Reset Password",
html_body: "<p>Here is a link to reset your password ... {{ link }}</p>",
transactional: true,
},
],
})
.then((response) => console.log(response))
.catch((error) => console.error(error));
Need more detail? Read the Emails endpoint guide →
Track behaviour from the browser
Add the JavaScript SDK to capture client-side events in real time.
<!-- GET THIS CODE IN YOUR ACCOUNT -->
<script src="https://app.bentonow.com/{...}.js" async defer></script>
<script>
window.addEventListener("bento:ready", function () {
if (typeof bento$ !== "undefined") {
bento$(function () {
// When a user is logged in, identify before calling view()
// if (logged_in) {
// bento.identify(email);
// }
bento.view();
});
}
});
</script>
API details
| Field | Value |
|---|---|
| Version | v1 |
| Base URL | https://app.bentonow.com/api/v1/ |
Rate limits
Rate limits keep the API stable. Reuse connections, back off on 429 responses, and cache where possible.
| Endpoint | Limit (per minute) |
|---|---|
/api/v1/fetch | 100 |
/api/v1/batch | 100 |
/api/v1/experimental | 100 |
Need higher limits? Contact support with your expected throughput and workload.
Common errors
| Code | Description | Debug suggestion |
|---|---|---|
400 | Bad Request | Confirm the payload matches the examples and required fields are present. |
401 | Unauthorized | Double-check the publishable key, secret key, and Site UUID. |
429 | Too Many Requests | Slow down requests, respect Retry-After, and add jitter to retry logic. |
500 | Internal Server Error | Verify the request format; if it persists, check Bento’s status page. |
BLOCKED | Cloudflare protection | Ensure requests are valid, include a User-Agent header, and confirm input data. |
What’s next?
- Generate or rotate your API keys in the dashboard
- Explore the Subscribers endpoint for batch imports
- Review the Events endpoint for tracking behaviour
- Dive into the Emails endpoint for transactional messages
- Join the Bento Discord if you need a second set of eyes on your integration.
Need the original Markdown? Open raw file