Skip to content

Data authority endpoint use

Using the Data Authority Endpoint (REST API)

This document provides a guide on how to interact with a Data Authority endpoint from a REST API perspective. Data Authority endpoints offer a standardized way to manage bitemporal entities, including CRUD operations and advanced querying capabilities.

Let’s assume we have a Data Authority endpoint for an entity named MyResource deployed under the base path /v1/my-app/myresource.

Common Headers

For most requests, you’ll need to include:

  • Authorization: Bearer token for authentication.
    • Example: Authorization: Bearer your_api_key_or_jwt_token
  • Content-Type: For POST and PUT requests, typically application/json.
    • Example: Content-Type: application/json
  • Accept: To specify the desired response format, typically application/json.
    • Example: Accept: application/json
  • X-Tenant-ID (or similar): Often required for multi-tenant systems, usually a UUID. The exact header name might vary.
    • Example: X-Tenant-ID: 123e4567-e89b-12d3-a456-426614174000

Standard Error Responses

Data Authority endpoints use standard HTTP status codes for errors:

  • 400 Bad Request: Invalid request payload, malformed JSON, missing required parameters.
  • 401 Unauthorized: Missing or invalid authentication token.
  • 403 Forbidden: Authenticated user does not have permission to perform the action.
  • 404 Not Found: The requested resource or entity ID does not exist.
  • 409 Conflict: The request could not be processed because of a conflict in the current state of the resource, such as an edit conflict (e.g. trying to update an older version).
  • 500 Internal Server Error: An unexpected error occurred on the server.

Error responses typically include a JSON body with more details:

{
  "error": "Short error code or type",
  "message": "Detailed error message",
  "requestId": "unique-request-id-for-logging"
}

CRUD Operations

These are the basic operations for creating, reading, updating, and deleting individual entities.

1. Create Entity

  • Endpoint: POST /v1/my-app/myresource
  • Description: Creates a new MyResource entity.
  • Request Body: JSON object representing the entity’s payload and any required creation metadata. The exact structure depends on the MyResourceInputPayload and how retrieveMetadata is configured for the endpoint.
  • Query Parameters:
    • effectiveAsOf (Optional, Long): Unix timestamp (milliseconds) for when this version of the entity becomes effective. Defaults to the current time if not provided.
  • Successful Response (200 OK or 201 Created): JSON object representing the EntityRecord of the newly created entity.

Example Request:

// POST /v1/my-app/myresource?effectiveAsOf=1678886400000
// Headers: Authorization, Content-Type, X-Tenant-ID
{
  "name": "New Resource Name",
  "description": "Optional description for the new resource.",
  "customField": "Some value"
}

Example Response (EntityRecord<MyResourcePayload, MyResourceMetadata>):

{
  "id": "generated-entity-uuid-1",
  "asOf": {
    "effective": 1678886400000,
    "recorded": 1678886405123 // Server-generated recorded time
  },
  "payload": {
    "id": "generated-entity-uuid-1", // Same as outer id
    "name": "New Resource Name",
    "description": "Optional description for the new resource.",
    "customField": "Some value"
  },
  "metadata": {
    "tenantId": "123e4567-e89b-12d3-a456-426614174000",
    "version": 1
  },
  "previousRecordId": null,
  "retired": false
}

2. Read Entity

  • Endpoint: GET /v1/my-app/myresource/{id}
  • Description: Retrieves a specific MyResource entity by its ID.
  • Path Parameter:
    • {id}: The unique identifier of the entity.
  • Query Parameters:
    • effectiveAsOf (Optional, Long): Unix timestamp (milliseconds). Retrieves the version of the entity effective at this time. Defaults to the current time.
    • recordedAsOf (Optional, Long): Unix timestamp (milliseconds). Retrieves the version of the entity as it was recorded at this time (for historical/audit views). Defaults to the current time.
  • Successful Response (200 OK): JSON object representing the EntityRecord.

Example Request:

GET /v1/my-app/myresource/generated-entity-uuid-1?effectiveAsOf=1678887000000&recordedAsOf=1678887000000
Headers: Authorization, Accept, X-Tenant-ID

Example Response (same structure as create response):

{
  "id": "generated-entity-uuid-1",
  "asOf": {
    "effective": 1678886400000, // Effective time of the record found
    "recorded": 1678886405123
  },
  "payload": {
    "id": "generated-entity-uuid-1",
    "name": "New Resource Name",
    "description": "Optional description for the new resource.",
    "customField": "Some value"
  },
  "metadata": {
    "tenantId": "123e4567-e89b-12d3-a456-426614174000",
    "version": 1
  },
  // ...
}

3. Update Entity

  • Endpoint: PUT /v1/my-app/myresource/{id}
  • Description: Updates an existing MyResource entity.
  • Path Parameter:
    • {id}: The unique identifier of the entity to update.
  • Request Body: JSON object with the fields to be updated.
  • Query Parameters:
    • effectiveAsOf (Optional, Long): Unix timestamp for when this update becomes effective.
  • Successful Response (200 OK): JSON object representing the EntityRecord of the updated entity (new version).

Example Request:

// PUT /v1/my-app/myresource/generated-entity-uuid-1?effectiveAsOf=1678887200000
// Headers: Authorization, Content-Type, X-Tenant-ID
{
  "description": "Updated description for the resource."
  // Only fields to be changed/updated are typically needed, but depends on EP.ip2Payload logic
}

Example Response (note the incremented version and new asOf times):

{
  "id": "new-record-uuid-for-update", // A new record ID is generated for the update
  "asOf": {
    "effective": 1678887200000,
    "recorded": 1678887205456
  },
  "payload": {
    "id": "generated-entity-uuid-1", // Entity ID remains the same
    "name": "New Resource Name", // Unchanged field from previous version
    "description": "Updated description for the resource.", // Updated field
    "customField": "Some value"
  },
  "metadata": {
    "tenantId": "123e4567-e89b-12d3-a456-426614174000",
    "version": 2 // Version typically increments
  },
  "previousRecordId": "old-record-uuid", // Points to the previous version's record ID
  "retired": false
}

4. Delete Entity

  • Endpoint: DELETE /v1/my-app/myresource/{id}
  • Description: Logically deletes an entity (marks it as retired). Data is not physically removed to maintain history.
  • Path Parameter:
    • {id}: The unique identifier of the entity to delete.
  • Query Parameters:
    • effectiveAsOf (Optional, Long): Unix timestamp for when this deletion becomes effective.
  • Successful Response (200 OK): JSON object representing the EntityRecord of the “deleted” (retired) entity.

Example Request:

DELETE /v1/my-app/myresource/generated-entity-uuid-1?effectiveAsOf=1678887500000
Headers: Authorization, X-Tenant-ID

Example Response (note retired: true):

{
  "id": "new-record-uuid-for-delete",
  "asOf": {
    "effective": 1678887500000,
    "recorded": 1678887505888
  },
  "payload": { // Payload is often preserved
    "id": "generated-entity-uuid-1",
    "name": "New Resource Name",
    "description": "Updated description for the resource.",
    "customField": "Some value"
  },
  "metadata": {
    "tenantId": "123e4567-e89b-12d3-a456-426614174000",
    "version": 3 // Version typically increments
  },
  "previousRecordId": "record-uuid-before-delete",
  "retired": true // Entity is now marked as retired
}

Query Operations

The Data Authority provides powerful querying capabilities to list and filter entities.

1. Initiate a Query / List Entities

  • Endpoint: POST /v1/my-app/myresource/query
  • Description: Lists entities based on specified filters, sorting, and pagination. The query is performed against the state of data as of the specified effectiveAsOf and recordedAsOf times.
  • Query Parameters (Optional):
    • effectiveAsOf (Long): Unix timestamp in milliseconds. Filters entities based on their state effective at this time. Defaults to the current system timestamp if omitted.
    • recordedAsOf (Long): Unix timestamp in milliseconds. Filters entities based on their state as recorded at this time (useful for historical/audit views). Defaults to the current system timestamp if omitted.
  • Request Body: A JSON Query object.

    Structure of the Query object (see cards.arda.common.lib.lang.query.Query):

    {
      "filter": { // Optional: A Filter object (e.g., {"EQ": {"locator": "status", "value": "ACTIVE"}})
                  // See Filter data classes (True, False, Not, And, Or, Eq, Neq, Gt, Gte, Lt, Lte, In, IsNull, Like, Contains, StartsWith, EndsWith)
        "EQ": { "locator": "status", "value": "ACTIVE" }
      },
      "sort": [ // Optional: List of Sort objects
        { "field": "name", "direction": "ASC" }, // ASC or DESC
        { "field": "createdAt", "direction": "DESC" }
      ],
      "paginate": { // Optional: Pagination object
        "index": 0, // 0-based page index
        "size": 20  // Number of results per page
        // thisPage, nextPage, previousPage are typically not sent in the initial query request body;
        // they are part of the response and used for subsequent page navigation.
      }
    }
    
    • filter: A Filter object defining the criteria. Supported types include logical operators (And, Or, Not) and comparison operators (Eq, Neq, Gt, Gte, Lt, Lte, In, IsNull, Like, Contains, StartsWith, EndsWith). The locator refers to a field in MyResourcePayload or MyResourceMetadata.
    • sort: An array of Sort objects, each specifying a field and direction (ASC or DESC).
    • paginate: A Pagination object specifying the index (0-based) of the page and the size (number of items per page).
  • Successful Response (200 OK): A PageResult object.
  • Example Request:

    // POST /v1/my-app/myresource/query?effectiveAsOf=1678886400000&recordedAsOf=1678887000000
    // Headers: Authorization, Content-Type, X-Tenant-ID
    {
      "filter": {
        "AND": [
          { "EQ": { "locator": "customField", "value": "Some value" } },
          { "EQ": { "locator": "status", "value": "ACTIVE" } }
        ]
      },
      "sort": [
        { "field": "name", "direction": "ASC" }
      ],
      "paginate": {
        "index": 0,
        "size": 10
      }
    }
    
  • Example Response (PageResult<MyResourcePayload, MyResourceMetadata>):

    {
      "thisPage": "opaquePageTokenForPage1", // Token representing the current page's query state
      "nextPage": "opaquePageTokenForPage2", // Token to fetch the next page, or empty/null if no next page
      "previousPage": null, // Token to fetch the previous page, or null if this is the first page
      "results": [
        {
          "id": "entity-uuid-A",
          "asOf": { "effective": 1678886400000, "recorded": 1678886405123 },
          "payload": { "id": "entity-uuid-A", "name": "Alpha Resource", "customField": "Some value", "status": "ACTIVE" },
          "metadata": { "tenantId": "123e4567-e89b-12d3-a456-426614174000", "version": 1 }
          // ... other fields ...
        },
        {
          "id": "entity-uuid-B",
          "asOf": { "effective": 1678800000000, "recorded": 1678800005123 },
          "payload": { "id": "entity-uuid-B", "name": "Bravo Resource", "customField": "Some value", "status": "ACTIVE" },
          "metadata": { "tenantId": "123e4567-e89b-12d3-a456-426614174000", "version": 2 }
          // ... other fields ...
        }
        // ... up to 'pageSize' results
      ]
    }
    

2. Navigate to Other Pages

  • Endpoint: GET /v1/my-app/myresource/query/{page}
  • Description: Retrieves a specific page of query results using a page token obtained from a previous PageResult. The query is performed against the state of data as of the specified effectiveAsOf and recordedAsOf times.
  • Path Parameter:
    • {page}: The opaque page token (e.g., the value from nextPage or previousPage of a PageResult). This token typically encodes the necessary query and pagination state.
  • Query Parameters (Optional):
    • effectiveAsOf (Long): Unix timestamp in milliseconds. Filters entities based on their state effective at this time. Defaults to the current system timestamp if omitted.
    • recordedAsOf (Long): Unix timestamp in milliseconds. Filters entities based on their state as recorded at this time. Defaults to the current system timestamp if omitted.
  • Successful Response (200 OK): A PageResult object for the requested page.
  • Example Request (using nextPage token from previous example):

    GET /v1/my-app/myresource/query/opaquePageTokenForPage2?effectiveAsOf=1678886400000&recordedAsOf=1678887000000
    Headers: Authorization, Accept, X-Tenant-ID
    
  • Example Response (another PageResult):

    {
      "thisPage": "opaquePageTokenForPage2",
      "nextPage": "opaquePageTokenForPage3", // Or empty/null
      "previousPage": "opaquePageTokenForPage1", // Token to get back to the first page
      "results": [
        // ... results for page 2 ...
      ]
    }
    
  • Using PageResult for Navigation:

    • thisPage: A token representing the state of the query for the current page. Could be used to “refresh” the current view if needed, though typically the client would hold onto the results.
    • nextPage: If not null or empty, use this token with the GET /query/{page} endpoint to fetch the next set of results.
    • previousPage: If not null, use this token to fetch the previous set of results.
    • results: An array of EntityRecord objects for the current page.

PlantUML Sequence Diagrams

Create Entity

uml diagram

Read Entity

uml diagram

Update Entity

uml diagram

Delete Entity

uml diagram

Initiate Query (POST /query)

uml diagram

Fetch Next Page of Query (GET /query/{page})

uml diagram

Comments