Skip to content
API Now! is currently in closed beta. We are constantly updating these guides as we release updates!

Version (Semantic Module)

← Back to Modules Reference

The Version semantic module maintains an automated, sequential version counter (1, 2, 3…) on an entity. It eliminates the need to write custom increment logic, database triggers, or collision detection code.

By decorating an integer property with Version, the backend automatically tracks how many times a record has been modified and protects your data against accidental overwrites when multiple users or systems edit the same record simultaneously.


AttributeSpecification
ScopeProperty (Applied to an integer or number property)
Data TypeInteger / Number
Initial Value1 on record creation (POST)
Increment BehaviorAutomatically increments by +1 on every update (PUT or PATCH)
HTTP ETag IntegrationEmitted as the strong HTTP ETag header (e.g., ETag: "1", ETag: "2")
Concurrency SafeguardsSupports If-Match HTTP headers and in-body version locks

When a client creates a new record via POST, the Serverless Engine automatically initializes the version property to 1. If the client attempts to pass a version value in the request body (such as { "version": 5 }), the runtime safely strips it and enforces 1.

Every time a record is updated via PUT or PATCH, the backend automatically executes an atomic database increment (version = version + 1). Because this increment is performed directly at the database level inside the transaction, version numbers are guaranteed to advance sequentially without race conditions.

Version numbers are system-managed. Clients cannot manually set, skip, or roll back the version value. Any version number supplied in the request body is stripped from the database write payload, ensuring clients cannot artificially manipulate record revisions.


Simultaneous Edit Protection (Concurrency Shield)

Section titled “Simultaneous Edit Protection (Concurrency Shield)”

In multi-user applications, two users often open the same record simultaneously. If both make changes, the person who saves last would normally overwrite the first person’s edits without knowing.

The Version semantic module enables Optimistic Concurrency Control (OCC) through two supported methods:

Section titled “Method 1: The Standard If-Match HTTP Header (Recommended)”

This is the standard HTTP approach (RFC 9110) supported by modern API clients, frontends, and SDKs:

  1. When your app fetches a record, it notes the current ETag header (e.g. ETag: "2").
  2. When submitting an update (PUT or PATCH), the app includes the header:
    If-Match: "2"
  3. If the record in the database is still version 2, the update succeeds and advances to version 3.
  4. If another user already saved an update in the meantime (making the record version 3), the database rejects the write and immediately returns 412 Precondition Failed (E_PRECONDITION_FAILED):
{
"type": "https://docs.apinow.app/errors/precondition-failed",
"title": "Precondition Failed",
"status": 412,
"code": "E_PRECONDITION_FAILED",
"detail": "If-Match precondition failed. Current version '3' does not match '2'.",
"hint": "Retrieve the latest version of the resource (GET /orders/101) before attempting this mutation.",
"instance": "/orders/101"
}

Method 2: Body-Based Version Locking (Payload Compatibility)

Section titled “Method 2: Body-Based Version Locking (Payload Compatibility)”

For clients or forms that prefer sending version values in the JSON body rather than HTTP headers:

  1. The client includes the expected version in the request payload:
    {
    "title": "Updated Contract Title",
    "version": 2
    }
  2. The runtime uses this value to lock the database update query (WHERE id = :id AND version = 2).
  3. If the record version has changed, the update affects 0 rows, and the engine throws a 409 Conflict (E_CONCURRENCY_CONFLICT):
    {
    "type": "https://docs.apinow.app/errors/conflict",
    "title": "Conflict",
    "status": 409,
    "code": "E_CONCURRENCY_CONFLICT",
    "detail": "Concurrency conflict: The record has been modified by another user."
    }

Assume an entity named Document has a property version decorated with the Version semantic module.

A client creates a new document:

POST /documents
Content-Type: application/json
{
"title": "Service Agreement"
}

Response (201 Created):

HTTP/1.1 201 Created
Location: /documents/doc_101
ETag: "1"
{
"data": {
"id": "doc_101",
"title": "Service Agreement",
"version": 1
}
}

Alice edits the title, passing the version tag she retrieved:

PATCH /documents/doc_101
If-Match: "1"
Content-Type: application/json
{
"title": "Service Agreement - Revised"
}

Response (200 OK):

HTTP/1.1 200 OK
ETag: "2"
{
"data": {
"id": "doc_101",
"title": "Service Agreement - Revised",
"version": 2
}
}

Bob, who still has version 1 open on his screen, tries to submit his own edits:

PATCH /documents/doc_101
If-Match: "1"
Content-Type: application/json
{
"title": "Service Agreement - Bob's Edits"
}

Response (412 Precondition Failed): The Serverless Engine blocks the write. Alice’s revision is preserved, and Bob’s app is prompted to refresh:

HTTP/1.1 412 Precondition Failed
Content-Type: application/problem+json
{
"type": "https://docs.apinow.app/errors/precondition-failed",
"title": "Precondition Failed",
"status": 412,
"code": "E_PRECONDITION_FAILED",
"detail": "If-Match precondition failed. Current version '2' does not match '1'."
}

  • Data Type Requirement: The Version semantic module can only be applied to an integer or numeric property. Tagging a String or Date property generates a Semantic Data Alignment [Error] during domain validation.
  • Positive Integers Only: When supplying a version in an update body, the value must be a positive integer (>= 1). Supplying strings, floats, or negative numbers returns a 422 Unprocessable Entity (E_VALIDATION_ERROR).
  • Displaying in Your UI: Because the version counter is a clean integer (1, 2, 3…), you can directly display it in frontend UI tables, badges (e.g. v3), or revision audit logs.