Upsert entity records
Changed on<Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>
Creates or updates up to 500 records in one of the app's entities in one call, matching them to stored records by the fields you name in key.
For each record you send, a stored record with the same values in every key field is updated, and otherwise a new record is created. For example, with "key": "order_number", re-sending an order updates it instead of adding a copy, so a sync job can send the same records again safely. An update merges like Update entity record, so a field you leave out keeps its value. Only the fields the entity's schema declares are stored, so a misspelled name is left out of the record instead of failing the call. Base44 always assigns id, created_date, updated_date, created_by, and created_by_id automatically, and ignores any of them you send.
key fields must be fields the entity's schema declares as a string, number, integer or boolean, and every record needs a value for each of them. Values are compared as the schema stores them, so "42" matches a stored 42 in a number field. When two records you send share a key, the later one wins. When several stored records share a key, the newest is updated.
Row-level security applies. Only stored records the entity's rls update rule lets you change are matched, so a record you can't change gets a new copy rather than an update, and new records must be covered by the rls create rule. Every record is checked before any is written, and one that fails rejects the call. If a call fails while it's writing, some records can already be stored, and sending it again finishes the job. Wait for the first call to finish before you retry: there's no Idempotency-Key, so two calls running at once can both create the same new record.
records in the response lists the created records first, then the updated ones. Like Create entity records, this doesn't trigger the app's webhooks, automations, or workflows.
<Note>This endpoint accepts a personal API key belonging to a user with access to the app. A read-only key is refused, and workspace API keys are not accepted.</Note>
Request
- Base URL: https://app.base44.com
- URL: https://app.base44.com/api/apps/{app_id}/entities/{entity_name}/upsert
- Auth: HTTP bearer
Path parameters
ID of the app that owns the entity.
Name of the entity, exactly as List entity schemas reports it. Don't pass User here. It doesn't fail, but it reads and writes a separate, disconnected set of records stored under that name, not the app's real user accounts, which are managed through their own endpoints.
Request body
Example request
{
"records": [
{
"amount": 4200,
"order_number": "A-1001",
"status": "paid"
},
{
"amount": 1800,
"order_number": "A-1002",
"status": "draft"
}
]
}Response
How many records were created and updated, and the records themselves.
Example response
{
"created": 1,
"updated": 1,
"records": [
{
"id": "6886b8d390dc7e2f4a2c91b4",
"created_date": "2026-06-05T08:12:44.902000Z",
"updated_date": "2026-06-05T08:12:44.902000Z",
"created_by": "jane@acme.com",
"created_by_id": "6874b0c2e1a94d0031bb77de",
"is_sample": false,
"order_number": "A-1002",
"status": "draft",
"amount": 1800
},
{
"id": "6886b8d390dc7e2f4a2c91b3",
"created_date": "2026-06-01T09:23:41.481000Z",
"updated_date": "2026-06-05T08:12:44.915000Z",
"created_by": "jane@acme.com",
"created_by_id": "6874b0c2e1a94d0031bb77de",
"is_sample": false,
"order_number": "A-1001",
"status": "paid",
"amount": 4200
}
]
}Changes
- ○
endpoint added
- ○