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

FieldValue
Versionv1
Base URLhttps://app.bentonow.com/api/v1/

Rate limits

Rate limits keep the API stable. Reuse connections, back off on 429 responses, and cache where possible.

EndpointLimit (per minute)
/api/v1/fetch100
/api/v1/batch100
/api/v1/experimental100

Need higher limits? Contact support with your expected throughput and workload.

Common errors

CodeDescriptionDebug suggestion
400Bad RequestConfirm the payload matches the examples and required fields are present.
401UnauthorizedDouble-check the publishable key, secret key, and Site UUID.
429Too Many RequestsSlow down requests, respect Retry-After, and add jitter to retry logic.
500Internal Server ErrorVerify the request format; if it persists, check Bento’s status page.
BLOCKEDCloudflare protectionEnsure requests are valid, include a User-Agent header, and confirm input data.

What’s next?

Was this helpful?

Need the original Markdown? Open raw file