curl --request POST \
--url https://api.paigeme.dev/v1/tables/{table}/rows \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"rows": [
{}
]
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({rows: [{}]})
};
fetch('https://api.paigeme.dev/v1/tables/{table}/rows', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.paigeme.dev/v1/tables/{table}/rows"
payload = { "rows": [{}] }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"success": true,
"data": {
"table": "<string>",
"schema": "<string>",
"inserted": 123,
"rows": [
{}
]
}
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}Insert rows into one of your tables
Inserts 1-50 rows and returns them as stored — generated primary keys, column defaults and trigger output included — so you can reference what you just wrote.
All-or-nothing. The batch is a single statement, so either every row lands or none does; there is no partial success to reconcile.
Every row must set the same columns, and at least one. To accept a column’s default, omit it from every row. A mixed batch is 400 inconsistent_rows; an empty row object is 400.
Every column you name is checked against the columns the table actually has; an unknown one is 400 unknown_column. Primary keys may be set — a collision is 409 unique_violation. A constraint the row violates is 400 constraint_violation, never an opaque 500.
Writes land in the public (production) schema by default — the one the live bot reads. Pass schema=preview only to write the dev sandbox.
Send an Idempotency-Key header to make a retry safe: the original response is replayed rather than the rows inserted twice.
A Paige platform table is 403 platform_table_forbidden; an unknown table is 404 table_not_found.
Only base tables are addressable. A view (or any other non-table relation) answers the same 404 table_not_found an unknown name does — including a view defined over a Paige platform table, which would otherwise be a writable alias for it.
Required scope: tables:write
curl --request POST \
--url https://api.paigeme.dev/v1/tables/{table}/rows \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"rows": [
{}
]
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({rows: [{}]})
};
fetch('https://api.paigeme.dev/v1/tables/{table}/rows', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.paigeme.dev/v1/tables/{table}/rows"
payload = { "rows": [{}] }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"success": true,
"data": {
"table": "<string>",
"schema": "<string>",
"inserted": 123,
"rows": [
{}
]
}
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}Authorizations
Project API key issued in Settings → API keys. Send it as Authorization: Bearer pk_live_….
Headers
Target project id, for an MCP OAuth bearer (mcp_at_…) attached to more than one project — get ids from GET /v1/projects. Matched case-insensitively.
Omit it and a READ falls back to the connection's default project; a mutation (any non-GET) on a connection with 2+ projects is rejected with 400 project_required — a write is never defaulted to a guessed project. A connection with exactly one project never needs the header.
Scopes are checked against the SELECTED project only, never a union across the connection.
For a pk_ API key the header selects nothing — one key is one project's context — but it IS validated: omit it and the key's own project is used, send it and it must name that project, otherwise the call is rejected with 403 project_not_attached (a blank value is 400 invalid_project_header, as above).
Path Parameters
Table name. Lowercase letters, digits and underscores only. Paige platform tables are rejected.
^[a-z_][a-z0-9_]{0,62}$Body
Which database schema to target: "public" (production, the default) or "preview" (dev sandbox).
public, preview Response
Success.
true Was this page helpful?
