Joins two lists of JSON rows on one or more key fields, like a VLOOKUP or SQL jo
Joins two lists of JSON rows on one or more key fields, like a VLOOKUP or SQL join: inner, left, right, full or anti. Keys match exactly, or normalized (case, spacing and number-as-text differences ignored). Returns joined rows plus match counts and unmatched rows. Up to 500 rows a side. $0.002 per left row sent (right rows free), $0.002 minimum. Same engine as nerolabs/dataset-join-merge.
Answeringour last check, 2026-10-21
1 of 1checks answered this week
503 msmedian answer time
$0.004listed price per call
$0.004price it asked us
Paid test badge: not yet. The checks above are free: we call the tool without paying and read the payment request it sends back. The Verified badge needs paid calls whose answers match the promised output, and nobody can buy a badge.
Endpoint
POST https://x402-agent-tools.nerolabs.workers.dev/data/join
| Category | Everything else |
|---|---|
| Provider host | x402-agent-tools.nerolabs.workers.dev |
| Networks | eip155:8453 |
| Payment schemes | exact |
| Self-reported calls, 30 days | 0 from 0 payers (the provider's figure, not ours) |
Our checks, last 30 days
| Day | Result | HTTP | Asked | Time |
|---|---|---|---|---|
| 2026-10-21 | valid payment request | 402 | $0.004 | 503 ms |
Example input (from the provider)
{
"body": {
"joinType": "left",
"keyMatching": "normalized",
"leftKeyFields": [
"domain"
],
"leftRows": [
{
"company": "Acme Ltd",
"domain": "acme.com"
},
{
"company": "Bolt Co",
"domain": "bolt.io"
}
],
"rightKeyFields": [
"website"
],
"rightRows": [
{
"employees": 40,
"website": " ACME.com"
}
]
},
"bodyType": "json",
"method": "POST",
"type": "http"
}
Promised output schema (from the provider)
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"input": {
"additionalProperties": false,
"properties": {
"body": {
"additionalProperties": false,
"properties": {
"includeJoinInfo": {
"description": "On by default: every row gets _joinStatus (\"matched\", \"left_only\", \"right_only\") and _matchCount. Set false for rows with only your own fields.",
"type": "boolean"
},
"joinType": {
"description": "Which rows to keep. left (default): every left row, enriched where a match exists. inner: matched rows only. right: every right row. full: everything from both sides. leftAnti: left rows with no match on the right. rightAnti: right rows with no match on the left. union: stack both lists, no key needed.",
"enum": [
"left",
"inner",
"right",
"full",
"leftAnti",
"rightAnti",
"union"
],
"type": "string"
},
"keyMatching": {
"description": "normalized (default): case-insensitive, trimmed, repeated spaces collapsed, 123 matches \"123\". exact: values must be identical.",
"enum": [
"normalized",
"exact"
],
"type": "string"
},
"leftKeyFields": {
"description": "The field name(s) on the left rows to match on, for example [\"email\"], or [\"firstName\",\"lastName\"] for a composite key. Required for every joinType except union.",
"items": {
"type": "string"
},
"type": "array"
},
"leftRows": {
"description": "The LEFT table: the main rows you want to keep or enrich. Each row is a JSON object; keys may differ between rows.",
"items": {
"type": "object"
},
"type": "array"
},
"multipleMatches": {
"description": "When one key matches several right rows. all (default): one output row per matching pair, like SQL. first: only the first matching right row, like VLOOKUP, so each left row appears once.",
"enum": [
"all",
"first"
],
"type": "string"
},
"onFieldConflict": {
"description": "When a right field has the same name as a left field. prefixRight (default): keep both, the right one renamed with rightFieldPrefix. keepLeft: ignore the right value. keepRight: overwrite the left value.",
"enum": [
"prefixRight",
"keepLeft",
"keepRight"
],
"type": "string"
},
"rightFieldPrefix": {
"description": "Prefix for conflicting right fields when onFieldConflict is prefixRight. Default \"right_\", so price becomes right_price.",
"type": "string"
},
"rightFields": {
"description": "Only copy these fields from the matching right row, like choosing VLOOKUP return columns. Leave out to copy every right field.",
"items": {
"type": "string"
},
"type": "array"
},
"rightKeyFields": {
"description": "The matching field name(s) on the right rows, in the same order as leftKeyFields, for example [\"contact_email\"]. Leave out when the right rows use the same names as the left.",
"items": {
"type": "string"
},
"type": "array"
},
"rightRows": {
"description": "The RIGHT table: the lookup rows to pull matching fields from. Each row is a JSON object.",
"items": {
"type": "object"
},
"type": "array"
}
},
"required": [
"leftRows",
"rightRows"
],
"type": "object"
},
"bodyType": {
"enum": [
"json",
"form-data",
"text"
],
"type": "string"
},
"method": {
"enum": [
"POST"
],
"type": "string"
},
"type": {
"const": "http",
"type": "string"
}
},
"required": [
"type",
"method",
"bodyType",
"body"
],
"type": "object"
},
"output": {
"properties": {
"example": {
"type": "object"
},
"type": {
"type": "string"
}
},
"required": [
"type"
],
"type": "object"
}
},
"required": [
"input"
],
"type": "object"
}