Mutation Engine
The Mutation Engine is the system responsible for all write operations in our API.
Any request that creates, updates, or deletes data is handled by the Mutation Engine. Instead of executing mutations immediately, requests are queued, validated, serialized, and processed asynchronously.
This is not an implementation detail — it is a core design choice that guarantees consistency, reliability, and predictable behavior under load.
Why the Mutation Engine exists
Directly writing to Airtable from a public API introduces hard problems:
- Strict rate limits.
- Eventual consistency.
- Transient failures.
- Ordering issues.
- Retry storms.
- Client-side duplication and race conditions.
Exposing those constraints directly to API consumers would make the API fragile and difficult to use. The Mutation Engine exists to absorb that complexity so clients don’t have to.
Our goals are simple:
- Mutations execute in the correct order.
- Temporary failures are retried automatically.
- Rate limits are respected centrally.
- Clients receive clear, consistent outcomes.
- No mutation is lost or executed twice unintentionally.
Follow the mutation lifecycle
Send a mutation request
Call POST /v2/... to create, update, or delete data. You can include idempotencyKey and callbackUrl.
Receive validation and acknowledgement
The API validates the request immediately. Valid mutations are queued and receive an immediate acknowledgement.
Wait for queued processing
Each Airtable base has an internal queue. Mutations are processed one at a time, in order.
Let the engine execute the mutation
The engine applies rate limits centrally and retries temporary failures automatically.
Receive the outcome
Use a signed callback, when provided, or observe your own system state.
Handle Mutation Engine responses
Upon requesting a mutation, you can receive either an acknowledgement or an internal failure response. The following examples show the response types.
{
"statusCode": 202,
"message": "The Mutation Engine has accepted the request for processing",
"data": {
"mutationId": "71823522-1bfb-49b8-885f-ceea9d782ad2",
"status": "queued"
}
}
{
"error": true,
"url": "https://onderwijsregio.onderwijsin.nl/api/v2/candidates",
"statusCode": 500,
"statusMessage": "Server Error",
"message": "Mutation engine rejected the mutation request due to validation errors",
"data": {
"idempotencyKey": "your-key",
"issues": [
... List of Zod validation issues ...
]
}
}
{
"error": true,
"url": "https://onderwijsregio.onderwijsin.nl/api/v2/candidates",
"statusCode": 500,
"statusMessage": "Server Error",
"message": "Unknown error from mutation engine",
"data": {
"idempotencyKey": "your-key"
}
}
{
"error": true,
"url": "https://onderwijsregio.onderwijsin.nl/api/v2/candidates",
"statusCode": 500,
"statusMessage": "Server Error",
"message": "Mutation engine declined the mutation request: {message}",
"data": {
"idempotencyKey": "your-key"
}
}
{
"statusCode": 202,
"message": "The Mutation Engine has accepted the request for processing",
"data": {
"mutationId": "71823522-1bfb-49b8-885f-ceea9d782ad2",
"status": "idempotency_hit",
"idempotencyKey": "your-idempotency-key",
}
}
Idempotent Operations
You may provide an idempotencyKey with mutation requests.
If the same key is sent multiple times:
- The mutation executes only once.
- Duplicate requests return the same
mutationId.
This is strongly recommended for:
- Network retries.
- Client restarts.
- Exactly-once semantics.
Callback URLs
Because mutations are asynchronous, the recommended way to observe completion is via callbacks.
If you provide a callbackUrl:
- The API sends the result by
POSTwhen processing finishes. - Callbacks are signed and retry-safe.
- Delivery failures are retried independently.
Callback payloads include:
mutationIdidempotencyKey(if provided)- Final status (
completedorfailed) - Result or error details
{
mutationId: '<uuid of operation>',
idempotencyKey: '<your provided idempotency key>',
status: 'completed',
result: { /* operation-specific result */ }
}
{
mutationId: '<uuid of operation>',
idempotencyKey: '<your provided idempotency key>',
status: 'failed',
result: {
errorCode: '<errorCode>',
status: '<http status code, if applicable>',
message: '<error message>',
attempts: '<number of attempts made>',
}
}
It is important that your callback endpoint rejects requests from untrusted sources. You should verify the signature included with each callback to ensure it originated from the Mutation Engine.
Read the callback-signatures guide to verify that callbacks were sent by the Mutation Engine.
Designing Your Integration
When integrating with the Mutation Engine, you should:
- Treat mutation responses as acknowledgements, not results.
- Use
idempotencyKeyfor safety. - Use callbacks for completion and error monitoring.
- Design your system to be event-driven, not synchronous.
- Assume mutations can take seconds, not milliseconds.
This model leads to simpler, safer, and more resilient systems.
Keep in touch with the latest
Sign up for our monthly deep dives - straight to your inbox.