Free table matching API
Paste two tables, choose the columns that identify a row, and see which rows match, which are missing from either side, and where a key is not unique. The form calls the same free API your code can call. The matching report waits in Storage for 24 hours.
curl -s -X POST https://aisenseapi.com/services/v1/table_match \
-H "Content-Type: application/json" \
-d '{"left":[{"customer_id":"00123","name":"Nordlys AS"},{"customer_id":"00456","name":"Fjord & Fjell"}],"right":[{"kundenummer":"00123","navn":"Nordlys AS"},{"kundenummer":"00999","navn":"Solvik"}],"keys":[{"left":"customer_id","right":"kundenummer"}]}'
{
"storage_id": "727c3223-e9ea-4260-aab8-d7bd1ccbdcc0",
"storage_url": "https://aisenseapi.com/services/v1/storage/727c3223-e9ea-4260-aab8-d7bd1ccbdcc0",
"sha256_hash": "e8a3a9c856db2397414e0e9d1a170bd33dc2a8bfe686385e94e1d75ecb0e7c78",
"bytes": 94,
"expire_timestamp": 1790760065,
"expire_datetime": "2026-09-30T09:21:05+00:00",
"content_type": "application/json",
"filename": "matches.json",
"operation": "table_match"
}Try it in the browser
This form posts to the same endpoint and shows the stored result. What you enter is sent to aisenseapi.com, and the result is kept for 24 hours at a link that anyone with the link can open.
How matching works
The report stored for the example at the top of the page:
{"matched":[{"left_index":0,"right_index":0}],"only_left":[1],"only_right":[1],"ambiguous":[]}
- Keys are compared exactly. With two key pairs, both must be equal. Nothing is trimmed and case is kept, so
00123does not match123, and the text"1"does not match the number1. - A key that is not unique is reported, never paired at random. When a key value found in both tables appears more than once in either of them, all those rows go into one
ambiguousgroup withleft_indicesandright_indices. - Every row lands in exactly one list:
matched,only_left,only_rightorambiguous. A row whose key is missing, null or empty never matches and is listed as only in its own table. - Indices are zero-based row numbers in the tables you sent. The report does not copy your data, so keep the tables to read the rows.
- Matched means the keys are equal, not that the other fields are. Comparing the values cell by cell is not part of this endpoint.
The API
POST https://aisenseapi.com/services/v1/table_match with Content-Type: application/json.
| Field | Required | Meaning |
|---|---|---|
left, right | yes | Lists of objects, one per row. |
keys | yes | List of {"left": column, "right": column} pairs. All must match. |
Key values can be strings, integers or true and false. Numbers with decimals are refused as keys; send decimal values and large IDs as strings. The report is stored as matches.json.
The answer is a Storage link
The endpoint never sends the converted file in its answer. It stores the result for 24 hours and answers with the same fields the Temporary Storage API answers with, plus what the result is:
| Field | Meaning |
|---|---|
storage_id, storage_url | Where the result is. A GET on the URL returns the bytes. |
sha256_hash, bytes | The digest and size of the stored bytes. |
expire_timestamp, expire_datetime | When the result is removed, 24 hours after it was stored. |
content_type, filename | What the result is and the name to save it under. |
operation | The endpoint that made it. |
The id and the expiry in the examples on this page come from a test run and are different on every call. The hash and the size are what the example request gives every time.
Anyone with the link can read the result until it expires, so do not send personal or confidential data. Stored results count against the Storage budget of 80 MB per IP address per day.
Limits
- The request body is at most 256 KB, both tables together.
- At most 5000 rows per table, 100 fields per row and 100 key pairs.
- The report is at most 2 MB.
Errors
A refused request stores nothing and answers with error. The endpoint's own refusals also carry fix, a sentence saying what to send instead.
| Status | When |
|---|---|
400 | The body is not a JSON object, a field is missing, unknown or has the wrong type, or the input breaks the rules above. |
405 | The method is not POST. |
413 | The request, the rows or the result is over a limit. |
415 | The Content-Type is not application/json. |
429 | More than 5000 requests from one IP address in 24 hours, or the day's Storage budget is used up. |
503 | The result could not be stored. Try again later. |
Questions
Is the table matching API free?
Yes. No API key, no account and no sign up. The limit is 5000 requests per IP address per 24 hours, and stored reports count against the Storage budget of 80 MB per IP address per day.
What happens when a key appears more than once?
When the key is in both tables, the rows are reported together as one ambiguous group, with the row numbers from both tables. The service never pairs duplicates at random.
Does it compare the other columns?
No. A match means the key columns are equal. Comparing the remaining values cell by cell is not part of this endpoint.
Does 00123 match 123?
No. Keys are compared exactly, with their type, and nothing is trimmed or converted.
Related tools
- JSON to CSV converter and CSV to JSON converter
- Table matching: compare two tables on key columns
- JSON formatter and JSON validator
- Image converter and image compression for JPEG, PNG and WebP
- Temporary Storage API, where every result is kept for 24 hours