Skip to content

Documentation

Configure code transformation

PUT /api/v1/exports/{export}/transformation

Switch between ordinary mapping and code for record or dataset processing.

Access

A Bearer API key for this workspace with write permission is required. The server also checks the owner’s permission for this resource and action. An inaccessible object is not disclosed.

Parameters

Path parameters: export. Use IDs from your own installation.

Example request parameters or JSON body:

{
  "mode": "mapping",
  "source": null,
  "base_version_id": null
}

mode is mapping, records, or dataset. base_version_id is required: use null for the first edit, then send the current converter_version_id. A version conflict prevents overwriting another edit. See modes.

Transformation language

Optional language accepts php, javascript, typescript, or python. If omitted, it preserves the current transformation version language; a new transformation uses php. It applies to new source, independently of collection language. Send new source when changing languages. If source is omitted or null, explicitly changing the language returns 422 with a language validation error. Repeating the current language is allowed and leaves the saved version unchanged.

Python uses def run(ctx):, reads ctx.params().get('items', []), and emits output dictionaries with ctx.emit(). Returning a list does not produce export output. Records mode preserves count/order; Dataset mode permits bounded filtering/aggregation. Endpoints transform only the current page. The response converter_language reports the attached version language. Use the current converter_version.id as base_version_id, or null for the first edit, to prevent overwriting concurrent changes.

Detailed Python transformation reference.

Response 200

The example is shortened; actual responses may include more fields. Sample IDs are placeholders.

{
  "id": 6,
  "code": "catalog-json",
  "name": "JSON catalog",
  "format": "json",
  "transformation_mode": "mapping",
  "schema": [
    {
      "source": "sku",
      "target": "id"
    }
  ]
}

Send the request

Set BASE to your installation URL without a trailing slash and API_KEY to a secret stored on your server. Client setup and browser JavaScript.

curl

curl --fail-with-body -X PUT "$BASE/api/v1/exports/6/transformation" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{
  "mode": "mapping",
  "source": null,
  "base_version_id": null
}
JSON

Node.js · server

// Node.js server example. Save as request.mjs.
const response = await fetch(process.env.BASE + "/api/v1/exports/6/transformation", {
  method: "PUT",
  headers: {
    Authorization: `Bearer ${process.env.API_KEY}`,
    Accept: "application/json",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({"mode":"mapping","source":null,"base_version_id":null}),
  signal: AbortSignal.timeout(120000)
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
console.log(await response.json());

Python

import json
import os
import urllib.request
import urllib.error

body = '{"mode":"mapping","source":null,"base_version_id":null}'.encode("utf-8")
request = urllib.request.Request(
    os.environ["BASE"] + "/api/v1/exports/6/transformation",
    method="PUT",
    headers={"Authorization": "Bearer " + os.environ["API_KEY"],
             "Accept": "application/json", "Content-Type": "application/json"},
    data=body,
)
try:
    with urllib.request.urlopen(request, timeout=120) as response:
        print(json.load(response))
except urllib.error.HTTPError as error:
    print(error.code, error.read().decode("utf-8", errors="replace"))
    raise

PHP · external client

<?php
$handle = curl_init(getenv("BASE") . "/api/v1/exports/6/transformation");
curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => "PUT",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 120,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("API_KEY"),
        "Accept: application/json",
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => <<<'JSON'
{"mode":"mapping","source":null,"base_version_id":null}
JSON,
]);
$content = curl_exec($handle);
$status = curl_getinfo($handle, CURLINFO_RESPONSE_CODE);
if ($content === false) {
    throw new RuntimeException(curl_error($handle));
}
curl_close($handle);
if ($status < 200 || $status >= 300) {
    throw new RuntimeException("HTTP $status: $content");
}
print_r(json_decode($content, true, 512, JSON_THROW_ON_ERROR));

Go

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
    "time"
    "strings"
)

func main() {
    body := strings.NewReader(`{"mode":"mapping","source":null,"base_version_id":null}`)
    request, err := http.NewRequest("PUT", os.Getenv("BASE") + "/api/v1/exports/6/transformation", body)
    if err != nil { panic(err) }
    request.Header.Set("Authorization", "Bearer " + os.Getenv("API_KEY"))
    request.Header.Set("Accept", "application/json")
    request.Header.Set("Content-Type", "application/json")
    client := &http.Client{Timeout: 120 * time.Second}
    response, err := client.Do(request)
    if err != nil { panic(err) }
    defer response.Body.Close()
    content, err := io.ReadAll(response.Body)
    if err != nil { panic(err) }
    if response.StatusCode < 200 || response.StatusCode >= 300 {
        panic(fmt.Sprintf("HTTP %d: %s", response.StatusCode, content))
    }
    fmt.Println(string(content))
}

If the request fails

401: check the key and its expiry. 403: check permissions, read/write scope, and 2FA. 404: check the ID and workspace. 422: check fields and resource state. 429: respect Retry-After. Errors and retries.