> Part of the walkerOS documentation. Project overview and full index: <https://www.walkeros.io/llms.txt>

# Web API Destination

<!-- -->

[Web](#)[ ](https://github.com/elbwalker/walkerOS/tree/main/packages/web/destinations/api)

<!-- -->

[Source code](https://github.com/elbwalker/walkerOS/tree/main/packages/web/destinations/api)[ ](https://www.npmjs.com/package/@walkeros/web-destination-api)

<!-- -->

[Package](https://www.npmjs.com/package/@walkeros/web-destination-api)

The web API destination allows you to send events from the browser to any HTTP endpoint with customizable data transformation and transport methods.

<!-- -->

Where this fits

Web API is a **web destination** in the walkerOS flow:

Sends events from the browser to any HTTP endpoint using fetch, XHR, or beacon transport with customizable request formatting.

## Installation[​](#installation "Direct link to Installation")

```
npm install @walkeros/web-destination-api
```

## Configuration[​](#configuration "Direct link to Configuration")

This <!-- -->destination<!-- --> uses the standard <!-- -->destination<!-- --> config wrapper (consent, data, env, id, ...). For the shared fields see [destination<!-- --> configuration](https://www.walkeros.io/docs/destinations.md#configuration). Package-specific fields live under `config.settings` and are listed below.

## Settings[​](#settings "Direct link to Settings")

| Property    | Type                           | Description                                      | More |
| ----------- | ------------------------------ | ------------------------------------------------ | ---- |
| `url*`      | `string`                       | The HTTP endpoint URL to send events to          |      |
| `headers`   | `Record<string, string>`       | Additional HTTP headers to include with requests |      |
| `method`    | `string`                       | HTTP method for the request                      |      |
| `transform` | `function`                     | Function to transform event data before sending  |      |
| `transport` | `'fetch' \| 'xhr' \| 'beacon'` | Transport method for sending requests            |      |

\* Required fields

## Mapping[​](#mapping "Direct link to Mapping")

This package does not define custom rule-level settings. For the standard rule fields (consent, condition, data, batch, name, policy) see [mapping](https://www.walkeros.io/docs/mapping.md).

## Examples

### Custom payload

An order event is reshaped via a data mapping into a custom JSON body for the API endpoint.

Event

```
{
  "name": "order complete",
  "data": {
    "id": "0rd3r1d",
    "currency": "EUR",
    "shipping": 5.22,
    "taxes": 73.76,
    "total": 555
  },
  "context": {
    "shopping": [
      "complete",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "product",
      "data": {
        "id": "ers",
        "name": "Everyday Ruck Snack",
        "color": "black",
        "size": "l",
        "price": 420
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "product",
      "data": {
        "id": "cc",
        "name": "Cool Cap",
        "size": "one size",
        "price": 42
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "gift",
      "data": {
        "name": "Surprise"
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "e8396d4f42807de7",
  "trigger": "load",
  "entity": "order",
  "action": "complete",
  "timestamp": 1700000502,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "data": {
    "map": {
      "order_id": "data.id",
      "amount": "data.total",
      "tax": "data.taxes",
      "shipping_cost": "data.shipping",
      "currency": "data.currency",
      "event_name": "name",
      "user_id": "user.id"
    }
  }
}
```

Out

```
sendWeb("https://api.example.com/events", "{\"order_id\":\"0rd3r1d\",\"amount\":555,\"tax\":73.76,\"shipping_cost\":5.22,\"currency\":\"EUR\",\"event_name\":\"order complete\",\"user_id\":\"us3r\"}", {
  "headers": {
    "traceparent": "00-0a1b2c3d4e5f60718293a4b5c6d7e8f9-e8396d4f42807de7-01"
  },
  "transport": "fetch"
})
```

### Entity action

A generic entity action event is forwarded to the configured API endpoint with the mapped data JSON body.

Event

```
{
  "name": "entity action",
  "data": {
    "string": "foo",
    "number": 1,
    "boolean": true,
    "array": [
      0,
      "text",
      false
    ]
  },
  "context": {
    "dev": [
      "test",
      1
    ]
  },
  "globals": {
    "lang": "elb"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "b2ed8a0f0850c4bb",
  "trigger": "test",
  "entity": "entity",
  "action": "action",
  "timestamp": 1700000500,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "data": "data"
}
```

Out

```
sendWeb("https://api.example.com/events", "{\"string\":\"foo\",\"number\":1,\"boolean\":true,\"array\":[0,\"text\",false]}", {
  "headers": {
    "traceparent": "00-0a1b2c3d4e5f60718293a4b5c6d7e8f9-b2ed8a0f0850c4bb-01"
  },
  "transport": "fetch"
})
```

### Page view

A page view is POSTed to the configured API endpoint with the event data section as the JSON body.

Event

```
{
  "name": "page view",
  "data": {
    "domain": "www.example.com",
    "title": "walkerOS documentation",
    "referrer": "https://www.walkeros.io/",
    "search": "?foo=bar",
    "hash": "#hash",
    "id": "/docs/"
  },
  "context": {
    "dev": [
      "test",
      1
    ]
  },
  "globals": {
    "pagegroup": "docs"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "ad52b1fe9990ff1a",
  "trigger": "load",
  "entity": "page",
  "action": "view",
  "timestamp": 1700000501,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "data": "data"
}
```

Out

```
sendWeb("https://api.example.com/events", "{\"domain\":\"www.example.com\",\"title\":\"walkerOS documentation\",\"referrer\":\"https://www.walkeros.io/\",\"search\":\"?foo=bar\",\"hash\":\"#hash\",\"id\":\"/docs/\"}", {
  "headers": {
    "traceparent": "00-0a1b2c3d4e5f60718293a4b5c6d7e8f9-ad52b1fe9990ff1a-01"
  },
  "transport": "fetch"
})
```

## Modes[​](#modes "Direct link to Modes")

* Integrated
* Bundled

```
import { startFlow } from '@walkeros/collector';
import { destinationAPI } from '@walkeros/web-destination-api';

const { collector, elb } = await startFlow({
  destinations: {
    api: {
      code: destinationAPI,
      config: {
        settings: {
          url: 'https://api.example.com/events',
        },
      },
    },
  },
});
```

Add to your `flow.json` destinations:

```
"destinations": {
  "api": {
    "package": "@walkeros/web-destination-api",
    "config": {
      "settings": {
        "url": "https://api.example.com/events"
      }
    }
  }
}
```

[See bundled mode setup](https://www.walkeros.io/docs/getting-started/modes/bundled.md) | [CLI reference](https://www.walkeros.io/docs/apps/cli.md)

## Usage[​](#usage "Direct link to Usage")

### Basic usage[​](#basic-usage "Direct link to Basic usage")

```
import { startFlow } from '@walkeros/collector';
import { destinationAPI } from '@walkeros/web-destination-api';

const { collector, elb } = await startFlow({
  destinations: {
    api: {
      code: destinationAPI,
      config: {
        settings: {
          url: 'https://api.example.com/events',
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            Authorization: 'Bearer your-token',
          },
        },
      },
    },
  },
});
```

### Advanced usage with transform[​](#advanced-usage-with-transform "Direct link to Advanced usage with transform")

```
import { startFlow } from '@walkeros/collector';
import { destinationAPI } from '@walkeros/web-destination-api';

const { collector, elb } = await startFlow({
  destinations: {
    api: {
      code: destinationAPI,
      config: {
        settings: {
          url: 'https://api.example.com/events',
          transport: 'fetch',
          transform: (event, config, mapping) => {
            // Custom transformation logic
            return JSON.stringify({
              timestamp: Date.now(),
              event_name: `${event.entity}_${event.action}`,
              properties: event.data,
              context: event.context,
            });
          },
        },
      },
    },
  },
});
```

### With batching[​](#with-batching "Direct link to With batching")

Set `config.batch` to send every event in one shared batch instead of one request per event. A bare number is the debounce `wait` window; an object tunes `wait`, `size`, and `age`. No `'* *'` wildcard mapping rule is needed.

Each flush is a single request whose body is a JSON array, one element per event. Mapping still applies per event, so an element is the event's mapped data when a rule produced some and the raw event otherwise. A `transform` runs per element, not once for the whole array. Batched requests carry no `traceparent` header: a batch can aggregate events from distinct traces, so there is no single identity to stamp.

```
import { startFlow } from '@walkeros/collector';
import { destinationAPI } from '@walkeros/web-destination-api';

const { collector, elb } = await startFlow({
  destinations: {
    api: {
      code: destinationAPI,
      config: {
        batch: { wait: 1000, size: 100 },
        settings: {
          url: 'https://api.example.com/events',
        },
      },
    },
  },
});
```

## Use cases[​](#use-cases "Direct link to Use cases")

### Sending to analytics API[​](#sending-to-analytics-api "Direct link to Sending to analytics API")

```
import { startFlow } from '@walkeros/collector';
import { destinationAPI } from '@walkeros/web-destination-api';

const { collector, elb } = await startFlow({
  destinations: {
    api: {
      code: destinationAPI,
      config: {
        settings: {
          url: 'https://analytics.example.com/track',
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'X-API-Key': 'your-api-key',
          },
          transform: (event) => {
            return JSON.stringify({
              event_type: `${event.entity}_${event.action}`,
              user_id: event.user?.id,
              session_id: event.user?.session,
              properties: event.data,
              timestamp: event.timing,
            });
          },
        },
      },
    },
  },
});
```

### Using beacon transport[​](#using-beacon-transport "Direct link to Using beacon transport")

For critical events that need to be sent even when the page is unloading:

```
// Add to existing startFlow config
const { collector, elb } = await startFlow({
  destinations: {
    criticalApi: {
      code: destinationAPI,
      config: {
        settings: {
          url: 'https://api.example.com/critical-events',
          transport: 'beacon', // Reliable for page unload scenarios
        },
      },
    },
  },
});
```

### Custom data mapping[​](#custom-data-mapping "Direct link to Custom data mapping")

Use mapping rules to control which events are sent:

```
// Add to existing startFlow config
const { collector, elb } = await startFlow({
  destinations: {
    api: {
      code: destinationAPI,
      config: {
        settings: {
          url: 'https://api.example.com/events',
        },
        mapping: {
          entity: {
            action: {
              data: 'data',
            },
          },
        },
      },
    },
  },
});
```

## Transport methods[​](#transport-methods "Direct link to Transport methods")

* **fetch** (default): Modern, promise-based HTTP requests
* **xhr**: Traditional XMLHttpRequest for older browser compatibility
* **beacon**: Uses Navigator.sendBeacon() for reliable data transmission during page unload
