{"uid":"cap_1al9dL4W2RBFtioSzwhhx","slug":"nero-labs-json-row-join-c8193589","name":"Nero Labs JSON Row Join","description":"Pay-per-call tools for AI agents, 31 in all: read web pages and RSS feeds, OCR, PDF text, transcription; email, phone and domain checks; UK, Irish and Polish company lookups and UK risk reports; website contacts, tech stack and SEO audits; PageSpeed; AI review, job post and row enrichment; data cleaning, joins, dedupe and diffs; US and EU compliance rules. No account or API key: pay each call in USDC on Base over x402.","url":"https://x402-agent-tools.nerolabs.workers.dev/data/join?utm_source=zero.xyz","method":"POST","headers":{},"bodySchema":{"type":"object","properties":{"joinType":{"enum":["left","inner","right","full","leftAnti","rightAnti","union"],"type":"string","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."},"leftRows":{"type":"array","items":{"type":"object"},"description":"The LEFT table: the main rows you want to keep or enrich. Each row is a JSON object; keys may differ between rows."},"rightRows":{"type":"array","items":{"type":"object"},"description":"The RIGHT table: the lookup rows to pull matching fields from. Each row is a JSON object."},"keyMatching":{"enum":["normalized","exact"],"type":"string","description":"normalized (default): case-insensitive, trimmed, repeated spaces collapsed, 123 matches \"123\". exact: values must be identical."},"rightFields":{"type":"array","items":{"type":"string"},"description":"Only copy these fields from the matching right row, like choosing VLOOKUP return columns. Leave out to copy every right field."},"leftKeyFields":{"type":"array","items":{"type":"string"},"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."},"rightKeyFields":{"type":"array","items":{"type":"string"},"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."},"includeJoinInfo":{"type":"boolean","description":"On by default: every row gets _joinStatus (\"matched\", \"left_only\", \"right_only\") and _matchCount. Set false for rows with only your own fields."},"multipleMatches":{"enum":["all","first"],"type":"string","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."},"onFieldConflict":{"enum":["prefixRight","keepLeft","keepRight"],"type":"string","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."},"rightFieldPrefix":{"type":"string","description":"Prefix for conflicting right fields when onFieldConflict is prefixRight. Default \"right_\", so price becomes right_price."}}},"responseSchema":{"type":"json","example":{"rows":[{"domain":"acme.com","company":"Acme Ltd","employees":40,"_joinStatus":"matched","_matchCount":1},{"domain":"bolt.io","company":"Bolt Co","_joinStatus":"left_only","_matchCount":0}],"summary":{"counts":{"matchedRows":1,"leftRowsMatched":1,"passthroughRows":1,"rightRowsMatched":1,"leftRowsUnmatched":1,"rightRowsUnmatched":0},"joinType":"left","warnings":[],"keyMatching":"normalized","leftKeyFields":["domain"],"leftMatchRate":0.5,"outputRowCount":2,"rightKeyFields":["website"],"rightMatchRate":1,"leftRecordCount":2,"multipleMatches":"all","rightRecordCount":1},"_example_note":"Real output, trimmed: long lists cut to their first items and long text shortened."}},"example":null,"exampleRequest":null,"tags":["x402"],"displayCostAmount":"0.002","displayCostAsset":"USDC","priceDynamic":false,"priceHint":null,"priceStatus":"priced","priceSource":"probe","requiresHandshake":false,"reviewCount":0,"rating":{"score":"0.00","successRate":"0.00","reviews":0,"stars":null,"state":"unrated"},"availabilityStatus":"unknown","priceObserved":null,"sessionDeposit":null,"pricing":{"kind":"static","summary":"$0.002/call","primary":{"kind":"static","protocol":"x402","network":"base","amountUsd":"0.002","per":"call","confidence":"exact"},"accepted":[{"kind":"static","protocol":"x402","network":"base","amountUsd":"0.002","per":"call","confidence":"exact"}]},"paymentMethods":[{"uid":"pm_L_KoX8h0S4pctHCaJRNdm","protocol":"x402","methodType":"crypto","chain":"base","mode":"charge","costAmount":"0.002","costPer":"request","priority":0,"asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","unit":"request","depositMicros":null,"planRef":null}],"brandName":null,"brandSlug":null,"brandBaseUrl":null,"brandDocsUrl":null,"whatItDoes":"Joins two lists of JSON rows on one or more key fields using inner, left, right, full, or anti join logic, like a VLOOKUP or SQL JOIN, with normalized or exact key matching.","exampleAgentPrompt":"I have two JSON arrays — one is my CRM contacts with an 'email' field and the other is a list of paid customers with a 'contact_email' field — can you do a left join on those key fields and bring over the 'plan' and 'mrr' columns from the right side, using normalized key matching?","exampleUseCases":[{"title":"Enrich CRM leads with company data","prompt":"I've got a list of leads from our CRM (each has a 'domain' field) and a separate list of company info rows (with a 'website' field and 'employees', 'industry' columns). Do a left join matching on those fields with normalized matching and only pull over 'employees' and 'industry' from the company list."},{"title":"Find unsubscribed contacts in mailing list","prompt":"I have my full mailing list as one JSON array with an 'email' key, and my unsubscribed list as another JSON array also with 'email'. Can you do a leftAnti join so I get back only the contacts who are NOT in the unsubscribed list?"},{"title":"Reconcile two product inventory tables","prompt":"I have two inventory snapshots as JSON row arrays — both have a 'sku' field. Do a full outer join on 'sku' with normalized matching so I can see which SKUs appear in one list but not the other, plus all the matched rows with fields from both sides."}],"resultDescription":"Returns a 'rows' array of merged JSON objects (each annotated with _joinStatus of 'matched', 'left_only', or 'right_only' and _matchCount unless disabled), plus a 'summary' object with counts of matched/unmatched rows on each side, match rates, join type used, key fields, and any warnings.","failureModes":["Missing leftKeyFields for non-union join types returns a validation error","Exceeding 500 rows on either side may be rejected or truncated","Key field names that don't exist in the row data result in zero matches and all rows unmatched","Exact keyMatching fails to match values that differ only in case or whitespace","multipleMatches:'first' silently drops duplicate right-side matches beyond the first"],"whenToPreferThis":"Choose this endpoint when you have two in-memory arrays of JSON objects that need to be combined, enriched, or compared by key — equivalent to a SQL JOIN or VLOOKUP — without standing up a database. It supports inner, left, right, full, and anti join semantics with normalized key matching, making it ideal for data enrichment pipelines, reconciliation tasks, and finding missing records across two datasets up to 500 rows each.","instructions":null,"reviewSummary":null,"reviewSummaryHighlights":null,"reviewSummaryConcerns":null,"reviewSummaryGeneratedAt":null,"activationCount":0,"lastUsedAt":null,"lastSuccessfullyRanAt":null,"lastHealthCheckAt":"2026-10-22T12:41:33.373Z","isFirstParty":false,"canonicalSlug":"nero-labs-json-row-join-c8193589"}