What is a Listener?

Listeners are the core of the Flatfile Platform. All of your configurations, from data transformations, to custom styling, to data export are done in a Listener. They hold the logic backing your Flatfile Spaces, defining the functionality of your implementation.

Fundamentally, a Listener is a function that listens for Events and takes action when they occur. This means your configurations are implemented in response to events. To understand how to configure a Listener, it’s important to understand the anatomy of an Event.

An Event-Driven System

Flatfile is an event-driven system, meaning interactions with Flatfile (clicking a button, editing a record, uploading a file, etc) trigger the publication of an Event.

Each Event contains information about its source and execution context including a domain, topic, context, and optionally, a payload.

Domainthe jurisdiction of the eventrecord, sheet, workbook, space, file, job, agent
Topica combination of a domain and an actionworkbook:created workbook:updated workbook:deleted
Contextdetailed information about context of the event
{ spaceId: "us_sp_1234", fileId: "us_fl_1234", ... }
Payload (optional)detailed information about execution of the event
{ status: "complete", workbookId: "us_wb_1234", ... }

Anatomy of a Listener

A Listener is a function designed to receive Events as they occur and take action by executing a callback function. For example, when a file is uploaded, a Listener can extract its data to a target sheet, or when a record is created, a Listener can validate the data.

The callback function can be as simple as logging the event or as advanced as integrating with external systems. Here is an example that logs the topic of any incoming event:

export default function (listener) {
  listener.on("**", (event) => {
    console.log(`Received event: ${event.topic}`);

This function is listening on ”**”, which is a wildcard that matches all events. For a complete list of events that can be listened to, see Event Topics.


Listeners will hear all events for an Environment, but the Events that a Listener responds to are configurable. You can target which events your code responds to in a few ways.

One way is to use a filter. A filter is a string that matches the topic of an event. For example, the filter “commit:created” will match any event of that topic.

A simple way to filter events is to use the shorthand syntax listener.on:

listener.on("commit:created", { sheet: "contacts" }, async (event) => {
  // Custom action responding to the commit

This is equivalent to:

listener.filter({ sheet: "contacts" }).on("commit:created", async (event) => {
  // Custom action responding to the commit

For cases when you want to use multiple listeners under one filter, this syntax may be useful:

export default function flatfileEventListener(listener) {
  listener.filter({ sheet: "contacts" }, (configure) => {
    configure.on("commit:created", async (event) => {
      // Custom action responding to the commit


Namespaces are another way to organize Listener configurations and target specific Events. If you have two different workflows, for example, you can assign them to different namespaces to keep them separate.

To direct a listener to act on events under a given namespace, simply use the listener.namespace method.

listener.namespace(['space:green'], (listener) => { ... })
listener.namespace(['space:red'], (listener) => { ... })

This will scope the listener to only respond to events that match the namespace.

Learn more about namespaces in the Namespaces guide.

Listener Types

Listeners can be hosted everywhere from your local machine to Flatfile’s secure cloud. The location of your listener determines the type of listener it is.

developmentdeveloper machinelocal listener for development
client-sideuser machinebrowser embeded listener
AgentFlatfile secure cloudFlatfile hosted server side listener
server-sideyour secure serverself-hosted server side listener

Flatfile Listeners can be either client-side or server-side.

Client-side listeners run in the end user’s web browser and respond to user interactions. Client-side listeners are perfect for scenarios that need to tap into values available in the browser, such as the current user’s session or the current page URL.

Server-side listeners run where deployed, either on your own servers or on Flatfile’s secure cloud, and can perform more complex tasks like running intensive calculations or using secured credentials to integrate with external systems.

Server-side listeners can leverage packages that need the capabilities of a server environment.


In Flatfile, an Agent refers to a server-side listener bundled and deployed to Flatfile to be hosted in our secure cloud. An Agent is deployed into an Environment and responds to all Events that occur there.

Agent Lifecycle

Developing your listener locally is easy with the Flatfile CLI. Simply run npx flatfile develop to start a local listener. Make changes to your listener code and the CLI will automatically pick up your changes and respond to Events.

Once you’re ready to deploy your listener, simply run npx flatfile deploy and your listener will be deployed to the specified environment.

Once an Agent is deployed, it will be listening for events in the environment it was deployed to.

Should you wish to update your listener, simply make your changes and run npx flatfile deploy again to upsert your Agent code.

Agent Conflicts

Any listener configured to respond to a given Environment will attempt to respond to Events emitted in that Environment.

This means that multiple listeners running in the same Environment will both attempt to perform operations based on the same Event. This could result in unexpected behavior and should be avoided.

We recommend using isolated environments to avoid conflicts with a deployed listener.

Agent Logs

When using Flatfile’s secure cloud to host your listener, you can view the executions of your Agent in the “Event Logs” tab of your dashboard.

Event logs are useful in monitoring and troubleshooting your listener. Each execution of your agent is recorded here, including any custom console logs you have configured in your listener code.


Failures occur when an Agent fails to execute properly. That means either an uncaught error is thrown, or the execution times out.

If you are catching and handling errors within your code, those executions will not be marked as failures. If you would prefer to see them marked this way, re-throw your error after handling to bubble it up to the execution handler.

export default function (listener) {
  listener.on("**", (event) => {
    try {
      // do something
    } catch (error) {
      // handle error
      throw error; // re-throw error to mark execution as failure

Learn More

Learn more about the Flatfile Platform in our other concept guides: