Publish

Publish sends your transformed data directly to an external API — row by row — as structured JSON HTTP requests. Instead of downloading a file and importing it yourself, WeTransform delivers each row of your transformed data to the endpoint of your choice.

What is Publish?

Publish is a data delivery mechanism attached to a Template. After a transformation completes, WeTransform reads the output and sends one HTTP request per row to your server, with a fully customizable JSON body. Think of it as an automated, row-level push of your transformed data into any system with an HTTP API.

Custom JSON payloads

Build any JSON structure visually, mapping your columns to the exact shape your API expects.

Rate limiting

Built-in sliding-window throttling so you never exceed your target API's rate limits.

Detailed reports

A CSV report is generated for every push, with request/response details for each row.

How It Works

Publish operates at the Template level. Once configured, every transformation using that template will automatically push results after completion.

  1. A sender submits data — A file is uploaded or sent via API to a transformation that uses your template.
  2. Transformation runs — WeTransform applies all your rules, validations, and corrections to produce the output.
  3. Publish fires — For each row in the transformation output, WeTransform builds a JSON body using your configured tree, and sends an HTTP request to your endpoint.
  4. Report is generated — A CSV report logs every request: status code, response body, errors, and the original row data.
  5. Email notification (optional) — If configured, a summary email with the report attached is sent to your chosen address.
One request per row. Each row in the transformation output triggers its own HTTP request. If your output has 500 rows, Publish will send 500 requests to your endpoint.

Use Cases

Feed an External Database

Push transformed product data, customer records, or inventory updates directly into your ERP, CRM, or PIM system's API.

Sync Data Between Systems

Receive supplier data, transform it to match your schema, and publish it to a downstream system — no manual import step.

Scheduled Pipelines

Combine Publish with scheduled transformations to build a fully automated ETL pipeline that runs daily without any intervention.

Third-Party Integrations

Send cleaned data to any HTTP endpoint: Zapier, Make (Integromat), n8n, or a custom microservice.

Setup

Publish is configured on a per-template basis. Navigate to your template's settings and enable the Publish feature.

1. Enable Publish

In your template settings, toggle Publish on. A disabled Publish configuration will be saved but will not fire after transformations.

2. Configure your HTTP endpoint

Provide the URL, HTTP method, headers, and optional cookies that WeTransform should use for each request. The JSON body is configured separately via the JSON Builder (see below).

  • URL: The endpoint that will receive each row's data (e.g., https://api.example.com/products).
  • Method: POST, PUT, PATCH, or any HTTP method your API requires.
  • Headers: Key-value pairs such as Authorization: Bearer <token> or Content-Type: application/json.
  • Cookies: Optional cookies to include in the request.
3. Build your JSON payload

Use the visual JSON Builder to define the structure of each request body. Map template columns to JSON properties.

4. (Optional) Configure rate limiting

If your target API has rate limits, set the maximum number of requests per time window.

5. (Optional) Set a notification email

Provide an email address to receive a summary report after each push execution, including the push report CSV and any transformation errors.

JSON Builder

The JSON Builder lets you visually design the JSON payload that will be sent for each row. It works as a tree of nodes, where each node represents either a structural element (object, array) or a value (column reference, literal string, number, etc.).

Column references

The most powerful node type is Column. It pulls the value from the transformation output for the current row. The JSON type (string, number, boolean) is automatically inferred from the column's data type configuration.

Example: if your template has columns product_name (text), price (number), and in_stock (boolean), you can build:

JSON Builder configuration
Root (object)
  |-- "name"       -> Column: product_name
  |-- "price"      -> Column: price
  |-- "available"  -> Column: in_stock
  |-- "source"     -> String: "WeTransform"

For a row where product_name = "Widget A", price = 19.99, in_stock = true, the resulting JSON body sent to your API would be:

Resulting HTTP request body
{
  "name": "Widget A",
  "price": 19.99,
  "available": true,
  "source": "WeTransform"
}

Node Types

Each node in the JSON tree has a type that determines how its value is resolved:

Type Description Example value
object A JSON object. Contains child nodes as key-value pairs. {"key": "value"}
array A JSON array. Contains child nodes as ordered elements. ["a", "b"]
column Pulls the value from the named template column for the current row. The JSON type (string, number, boolean) is automatically inferred from the column's data type. "Widget A" or 19.99
string A static string literal. "hello"
number A static numeric literal. 42
boolean A static boolean literal. true
json A raw JSON string that will be parsed and embedded as-is. Useful for columns that contain JSON data. {"nested": true}
null A JSON null literal. null
Column type inference

When using column nodes, the JSON type is determined by the template column's data type:

Column data type JSON type
Text, Value, URL, Email, Imagestring
Number (standard decimal separator)number
Number (custom thousands/decimal separator)string
Date (most formats)string
Date (year-only or Unix timestamp)number
Booleanboolean
JSONjson (embedded as parsed object)
Omit if empty

Each node has an "omit if empty" option. When enabled, the node is excluded from the output if its resolved value is null, an empty string, or an empty array. This keeps your payloads clean by avoiding unnecessary null fields.

HTTP Settings

Configure how each request is sent to your API:

Configuration example
{
  "url": "https://api.example.com/products",
  "method": "POST",
  "headers": {
    "Authorization": "Bearer sk-abc123...",
    "Content-Type": "application/json",
    "X-Custom-Header": "my-value"
  },
  "cookies": {}
}
Field Required Description
url Yes The full URL of the endpoint to receive each request.
method Yes HTTP method: GET, POST, PUT, DELETE, or PATCH.
headers No Key-value pairs for request headers. Use this for authentication tokens, content types, etc.
cookies No Key-value pairs for cookies to include in the request.
Encryption: Your HTTP settings (URL, headers, authentication tokens) are stored encrypted at rest. They are only decrypted at execution time.

Rate Limiting

Many APIs enforce rate limits (e.g., "max 100 requests per minute"). Publish includes a built-in sliding-window rate limiter that automatically throttles requests to stay within your configured limits.

Configuration
rate_limit_requests

Maximum number of requests allowed in the time window. Must be ≥ 1.

rate_limit_period

Time window in seconds. Must be ≥ 1.

Examples
Requests Period Meaning
10060Max 100 requests per minute
240030Max 2,400 requests per 30 seconds (burst-friendly)
101Max 10 requests per second
emptyemptyNo rate limiting — requests are sent as fast as possible

When the limit is reached, Publish automatically pauses and resumes once the window allows more requests. No rows are dropped — they are simply delayed.

Reports & Email Notifications

After every push execution, a detailed CSV report is generated and stored. Each row in the report corresponds to one HTTP request.

Report columns
Column Description
row_numberThe row index from the transformation output.
hashAn MD5 hash of the row data, useful for deduplication.
unique_attribute_valueThe value of the template's unique column (if configured).
is_successfultrue or false — whether the request returned a 2xx status.
request_bodyThe JSON body that was sent.
response_status_codeThe HTTP status code returned by your server.
response_bodyThe response body returned by your server.
error_messageError description if the request failed.
source columns...Original values from the source file, included for traceability.
Email notifications

If you provide a notification email, WeTransform sends a summary after each push execution. The email includes:

  • Transformation statistics: rows in source, rows processed, rows in error, success percentage.
  • Push statistics: total requests, successful requests, failed requests, success percentage.
  • Attachments: the push report CSV, and (if there were transformation errors) the transformation error report CSV.

The push report is also available for download for 30 days from the submission details page.

Examples

Simple product sync

Push product data to an external catalog API:

JSON tree
Root (object)
  |-- "sku"         -> Column: product_sku
  |-- "name"        -> Column: product_name
  |-- "price"       -> Column: unit_price
  |-- "currency"    -> String: "EUR"
  |-- "in_stock"    -> Column: available
Output for one row
{
  "sku": "PROD-001",
  "name": "Ergonomic Chair",
  "price": 299.99,
  "currency": "EUR",
  "in_stock": true
}
Nested structure with arrays

Build complex payloads with nested objects and arrays:

JSON tree
Root (object)
  |-- "id"          -> Column: employee_id
  |-- "person"      -> Object
  |     |-- "first" -> Column: first_name
  |     |-- "last"  -> Column: last_name
  |     |-- "email" -> Column: email
  |-- "tags"        -> Array
  |     |-- [0]     -> Column: department
  |     |-- [1]     -> String: "imported"
  |-- "active"      -> Boolean: true
Output for one row
{
  "id": "EMP-042",
  "person": {
    "first": "Alice",
    "last": "Martin",
    "email": "alice.martin@example.com"
  },
  "tags": ["Engineering", "imported"],
  "active": true
}
Using "omit if empty"

Keep your API payloads clean by omitting fields when values are missing:

JSON tree (omit_if_empty enabled on "phone" and "notes")
Root (object)
  |-- "name"   -> Column: contact_name
  |-- "email"  -> Column: contact_email
  |-- "phone"  -> Column: contact_phone    (omit if empty)
  |-- "notes"  -> Column: contact_notes    (omit if empty)

If contact_phone and contact_notes are empty for a row, the output will be:

Output (clean, no nulls)
{
  "name": "Bob Smith",
  "email": "bob@example.com"
}

Deliver your data automatically

Push transformed data directly to your systems — no file downloads, no manual imports.

Go to dashboard
© 2026