API Reference

https://api.serialized.io/

Authentication

accessKey

in
header
name
Serialized-Access-Key

secretAccessKey

in
header
name
Serialized-Secret-Access-Key

Event Sourcing API

Store events

POST
/aggregates/{aggregateType}/events

Stores all events in the request atomically. All events must refer to the same aggregate id.

Parameters
aggregateType Required

The name of the aggregate type.

Parameters
aggregateId: string (uuid)
events: object[]
expectedVersion: integer

Optional version number enabling optimistic concurrency control in a multi-threaded scenario.

Example
{
  "aggregateId": "2c3cf88c-ee88-427e-818a-ab0267511c84",
  "events": [
    {
      "eventId": "f2c8bfc1-c702-4f1a-b295-ef113ed7c8be",
      "eventType": "PaymentProcessed",
      "data": {
        "paymentMethod": "CARD",
        "amount": 1000,
        "currency": "SEK"
      },
      "encryptedData": "string"
    }
  ],
  "expectedVersion": 1
}
Responses
200 OK

Event(s) successfully stored.

400 Bad Request

Invalid aggregate type name.

409 Conflict

Conflict due to expected version missmatch.

422 Unprocessable Entity

If invalid request body

Delete all aggregates by type

DELETE
/aggregates/{aggregateType}

Permanently delete all aggregates, including all events, for given aggregate type.

Parameters
aggregateType Required

The name of the aggregate type

deleteToken

Valid delete token. Will be included in the response to the first DELETE request.

Responses
200 OK

The generated temporary delete token needed to permanently delete all aggregates. The token will be valid for ten minutes and must be passed as a query parameter to trigger the delete of all the aggregates.

204 No Content

If delete token was valid and the aggregate was successfully deleted.

403 Forbidden

If delete token was invalid or expired.

Response Example (200 OK)
{
  "deleteToken": "12c3780f-2dcb-340f-5532-5693be83f21c"
}

Check if an aggregate exists

HEAD
/aggregates/{aggregateType}/{aggregateId}
Parameters
aggregateType Required

The name of the aggregate type

aggregateId Required

The unique id of the aggregate

Responses
200 OK

If aggregate exists

404 Not Found

If aggregate does not exist.

Delete an aggregate

DELETE
/aggregates/{aggregateType}/{aggregateId}

Permanently delete an aggregate, including all events.

Parameters
aggregateType Required

The name of the aggregate type

aggregateId Required

The unique id of the aggregate

deleteToken

Valid delete token. Will be included in the response to the first DELETE request.

Responses
200 OK

The generated temporary delete token needed to permanently delete the aggregate. The token will be valid for ten minutes and must be passed as a query parameter to trigger the delete of the aggregate.

204 No Content

If delete token was valid and the aggregate was successfully deleted.

403 Forbidden

If delete token was invalid or expired.

Response Example (200 OK)
{
  "deleteToken": "12c3780f-2dcb-340f-5532-5693be83f21c"
}

Load all events for an aggregate

GET
/aggregates/{aggregateType}/{aggregateId}

By loading all events for a single aggregate we can derive the current state.

Parameters
aggregateType Required

The name of the aggregate type

aggregateId Required

The unique id of the aggregate

since

Optional version number to start from

Responses
200 OK

Aggregate successfully loaded

404 Not Found

If aggregate not found.

Response Example (200 OK)
{
  "aggregateId": "22c3780f-6dcb-440f-8532-6693be83f21c",
  "aggregateVersion": 1,
  "aggregateType": "payment",
  "events": [
    {
      "eventId": "f2c8bfc1-c702-4f1a-b295-ef113ed7c8be",
      "eventType": "PaymentProcessed",
      "data": {
        "paymentMethod": "CARD",
        "amount": 1000,
        "currency": "SEK"
      },
      "encryptedData": "string"
    }
  ]
}

Event Feed API

Get event feeds overview

GET
/feeds

Overview showing number of batches, aggregates and events per aggregate type.

Responses
200 OK

Feeds successfully received

Response Example (200 OK)
{
  "feeds": [
    {
      "aggregateType": "payment",
      "aggregateCount": 1337,
      "batchCount": 7331,
      "eventCount": 9977
    }
  ]
}

Get current global sequence number

HEAD
/feeds/_all

Get current global sequence number at head for all feeds

Responses
200 OK

OK

Get feed of events for all types

GET
/feeds/_all

Get all events for all aggregates for all types (feed names). The payload is returned with the event batches in insertion order, each with a unique sequence number.

Parameters
since

Optional sequence number to start from

limit

Optional response limit

from

Optional ISO 8601 date-time string to start from, eg. 2017-07-21T17:32:28. Must be used in combination with 'to' parameter.

to

Optional ISO 8601 data-time string to stop at, eg. 2017-07-21T17:32:28. Must be used in combination with 'from' parameter.

Responses
200 OK

Feed successfully received

Response Example (200 OK)
{
  "entries": [
    {
      "sequenceNumber": 12314,
      "aggregateId": "22c3780f-6dcb-440f-8532-6693be83f21c",
      "timestamp": 1503386583474,
      "events": [
        {
          "eventId": "f2c8bfc1-c702-4f1a-b295-ef113ed7c8be",
          "eventType": "PaymentProcessed",
          "data": {
            "paymentMethod": "CARD",
            "amount": 1000,
            "currency": "SEK"
          },
          "encryptedData": "string"
        }
      ]
    }
  ],
  "hasMore": false,
  "currentSequenceNumber": 123456
}

Get current sequence number

HEAD
/feeds/{name}

Get current sequence number at head for a given feed

Parameters
name Required

The name of the feed

Responses
200 OK

OK

Get feed of events

GET
/feeds/{name}

Get all events for all aggregates given a type (feed name). The payload is returned with the event batches in insertion order, each with a unique sequence number.

Parameters
name Required

The name of the feed (aggregate type)

since

Optional sequence number to start from

limit

Optional response limit

from

Optional ISO 8601 date-time string to start from, eg. 2017-07-21T17:32:28. Must be used in combination with 'to' parameter.

to

Optional ISO 8601 data-time string to stop at, 2017-07-21T17:32:28. Must be used in combination with 'from' parameter.

Responses
200 OK

Feed successfully received

Response Example (200 OK)
{
  "entries": [
    {
      "sequenceNumber": 12314,
      "aggregateId": "22c3780f-6dcb-440f-8532-6693be83f21c",
      "timestamp": 1503386583474,
      "events": [
        {
          "eventId": "f2c8bfc1-c702-4f1a-b295-ef113ed7c8be",
          "eventType": "PaymentProcessed",
          "data": {
            "paymentMethod": "CARD",
            "amount": 1000,
            "currency": "SEK"
          },
          "encryptedData": "string"
        }
      ]
    }
  ],
  "hasMore": false,
  "currentSequenceNumber": 123456
}

Event Reaction API

List reaction definitions

GET
/reactions/definitions

List all reaction definitions

Responses
200 OK

successful operation

Response Example (200 OK)
{
  "definitions": [
    {
      "reactionName": "payment-processed-email-reaction",
      "feedName": "payment",
      "reactOnEventType": "PaymentProcessed",
      "cancelOnEventTypes": [
        "OrderCanceledEvent"
      ],
      "triggerTimeField": "my.event.data.field",
      "offset": "PT1H",
      "action": {
        "actionType": "string"
      }
    }
  ]
}

Create reaction definition

POST
/reactions/definitions

Create a new reaction definition

The reaction definition

Example
{
  "reactionName": "payment-processed-email-reaction",
  "feedName": "payment",
  "reactOnEventType": "PaymentProcessed",
  "cancelOnEventTypes": [
    "OrderCanceledEvent"
  ],
  "triggerTimeField": "my.event.data.field",
  "offset": "PT1H",
  "action": {
    "actionType": "string"
  }
}
Responses
200 OK

successful operation

409 Conflict

if name not unique

422 Unprocessable Entity

If invalid request body

Delete a reaction definition

DELETE
/reactions/definitions/{reactionName}
Parameters
reactionName Required

The reaction name

Responses
404 Not Found

If reaction definition not found

Get reaction definition

GET
/reactions/definitions/{reactionName}
Parameters
reactionName Required

The reaction name

Responses
200 OK

successful operation

404 Not Found

If reaction definition not found

Response Example (200 OK)
{
  "reactionName": "payment-processed-email-reaction",
  "feedName": "payment",
  "reactOnEventType": "PaymentProcessed",
  "cancelOnEventTypes": [
    "OrderCanceledEvent"
  ],
  "triggerTimeField": "my.event.data.field",
  "offset": "PT1H",
  "action": {
    "actionType": "string"
  }
}

Update reaction definition

PUT
/reactions/definitions/{reactionName}
Parameters
reactionName Required

The reaction name

The reaction definition

Example
{
  "reactionName": "payment-processed-email-reaction",
  "feedName": "payment",
  "reactOnEventType": "PaymentProcessed",
  "cancelOnEventTypes": [
    "OrderCanceledEvent"
  ],
  "triggerTimeField": "my.event.data.field",
  "offset": "PT1H",
  "action": {
    "actionType": "string"
  }
}
Responses
200 OK

successful operation

400 Bad Request

if ID mismatch

422 Unprocessable Entity

If invalid request body

Event Projection API

Get projections overview

GET
/projections

Includes projection names and count

Responses
200 OK

successful operation

Response Example (200 OK)
{
  "projections": [
    {
      "projectionName": "shipping-stats",
      "feedName": "shipment",
      "aggregated": false,
      "projectionsCount": 1977
    }
  ]
}

List projection definitions

GET
/projections/definitions

List all definitions

Responses
200 OK

successful operation

Response Example (200 OK)
{
  "definitions": [
    {
      "projectionName": "orders",
      "feedName": "order",
      "handlers": [
        {
          "eventType": "OrderCancelledEvent",
          "functionUri": "https://your-server.com/lambda",
          "functions": [
            {
              "function": "inc",
              "targetSelector": "$.projection.orders[?]",
              "eventSelector": "$.event[?]",
              "targetFilter": "@.orderId == $.event.orderId",
              "eventFilter": "@.orderAmount > 4000"
            }
          ]
        }
      ]
    }
  ]
}

Create a projection definition

POST
/projections/definitions

Create a new definition

Definition of the projection

Example
{
  "projectionName": "orders",
  "feedName": "order",
  "handlers": [
    {
      "eventType": "OrderCancelledEvent",
      "functionUri": "https://your-server.com/lambda",
      "functions": [
        {
          "function": "inc",
          "targetSelector": "$.projection.orders[?]",
          "eventSelector": "$.event[?]",
          "targetFilter": "@.orderId == $.event.orderId",
          "eventFilter": "@.orderAmount > 4000"
        }
      ]
    }
  ]
}
Responses
200 OK

successful operation

409 Conflict

if ID not unique

422 Unprocessable Entity

If invalid request body

Get projection definition

GET
/projections/definitions/{projectionName}
Parameters
projectionName Required

The projection name

Responses
200 OK

successful operation

404 Not Found

If definition not found

Response Example (200 OK)
{
  "projectionName": "orders",
  "feedName": "order",
  "handlers": [
    {
      "eventType": "OrderCancelledEvent",
      "functionUri": "https://your-server.com/lambda",
      "functions": [
        {
          "function": "inc",
          "targetSelector": "$.projection.orders[?]",
          "eventSelector": "$.event[?]",
          "targetFilter": "@.orderId == $.event.orderId",
          "eventFilter": "@.orderAmount > 4000"
        }
      ]
    }
  ]
}

Update a projection definition

PUT
/projections/definitions/{projectionName}

Create or update a definition

Parameters
projectionName Required

The projection name

Definition of the projection

Example
{
  "projectionName": "orders",
  "feedName": "order",
  "handlers": [
    {
      "eventType": "OrderCancelledEvent",
      "functionUri": "https://your-server.com/lambda",
      "functions": [
        {
          "function": "inc",
          "targetSelector": "$.projection.orders[?]",
          "eventSelector": "$.event[?]",
          "targetFilter": "@.orderId == $.event.orderId",
          "eventFilter": "@.orderAmount > 4000"
        }
      ]
    }
  ]
}
Responses
200 OK

successful operation

422 Unprocessable Entity

If invalid request body

Delete projection definition

DELETE
/projections/definitions/{projectionName}
Parameters
projectionName Required

The projection name

Responses
200 OK

successful operation

404 Not Found

If definition not found

List single projections

GET
/projections/single/{projectionName}

List all single projections

Parameters
projectionName Required

The projection name

sort

Sort string. Any combination of the following fields: projectionId, reference, createdAt, updatedAt. Add '+' and '-' prefixes to indicate ascending/descending sort order. Ascending order is default.

skip

Number of entries to skip

limit

Max number of entries to include in response

Responses
200 OK

successful operation

Response Example (200 OK)
{
  "projections": [
    {
      "projectionId": "22c3780f-6dcb-440f-8532-6693be83f21c",
      "createdAt": 1523518143967,
      "updatedAt": 1523518144467,
      "data": "object"
    }
  ],
  "totalCount": 1
}

Delete/recreate single projections

DELETE
/projections/single/{projectionName}

This call deletes all existing projections and starts a rebuild from the beginning of the event history. Keep in mind that this might take a while.

Parameters
projectionName Required

The projection name

Responses
200 OK

successful operation

404 Not Found

If definition not found

Get single projection

GET
/projections/single/{projectionName}/{projectionId}
Parameters
projectionName Required

The projection name

projectionId Required

The projectionId

Responses
200 OK

successful operation

Response Example (200 OK)
{
  "projectionId": "22c3780f-6dcb-440f-8532-6693be83f21c",
  "createdAt": 1523518143967,
  "updatedAt": 1523518144467,
  "data": "object"
}

List aggregated projections

GET
/projections/aggregated

List all aggregated projections

Parameters
sort

Sort string. Any combination of the following fields: projectionId, createdAt, updatedAt. Add '+' and '-' prefixes to indicate ascending/descending sort order. Ascending order is default.

skip

Number of entries to skip

limit

Max number of entries to include in response

Responses
200 OK

successful operation

Response Example (200 OK)
{
  "projections": [
    {
      "projectionId": "22c3780f-6dcb-440f-8532-6693be83f21c",
      "createdAt": 1523518143967,
      "updatedAt": 1523518144467,
      "data": "object"
    }
  ],
  "totalCount": 1
}

Get aggregated projection

GET
/projections/aggregated/{projectionName}
Parameters
projectionName Required

The projection name

Responses
200 OK

successful operation

Response Example (200 OK)
{
  "projectionId": "22c3780f-6dcb-440f-8532-6693be83f21c",
  "createdAt": 1523518143967,
  "updatedAt": 1523518144467,
  "data": "object"
}

Delete/recreate aggregated projections

DELETE
/projections/aggregated/{projectionName}

This call deletes all existing projections and starts a rebuild from the beginning of the event history. Keep in mind that this might take a while.

Parameters
projectionName Required

The projection name

Responses
200 OK

successful operation

404 Not Found

If definition not found

Schema Definitions

Event

Parameters
eventId: string (uuid)
eventType: string
data: object

Optional user defined event data map

encryptedData: string

Optional client-side encrypted payload. Max 65535 bytes.

Example
{
  "eventId": "f2c8bfc1-c702-4f1a-b295-ef113ed7c8be",
  "eventType": "PaymentProcessed",
  "data": {
    "paymentMethod": "CARD",
    "amount": 1000,
    "currency": "SEK"
  },
  "encryptedData": "string"
}

ProjectionDefinitions

Parameters
definitions: object[]
Example
{
  "definitions": [
    {
      "projectionName": "orders",
      "feedName": "order",
      "handlers": [
        {
          "eventType": "OrderCancelledEvent",
          "functionUri": "https://your-server.com/lambda",
          "functions": [
            {
              "function": "inc",
              "targetSelector": "$.projection.orders[?]",
              "eventSelector": "$.event[?]",
              "targetFilter": "@.orderId == $.event.orderId",
              "eventFilter": "@.orderAmount > 4000"
            }
          ]
        }
      ]
    }
  ]
}

ProjectionDefinition

Parameters
projectionName: string

Name of the projection type

feedName: string

Name of the feed

handlers: object[]
Example
{
  "projectionName": "orders",
  "feedName": "order",
  "handlers": [
    {
      "eventType": "OrderCancelledEvent",
      "functionUri": "https://your-server.com/lambda",
      "functions": [
        {
          "function": "inc",
          "targetSelector": "$.projection.orders[?]",
          "eventSelector": "$.event[?]",
          "targetFilter": "@.orderId == $.event.orderId",
          "eventFilter": "@.orderAmount > 4000"
        }
      ]
    }
  ]
}

Handler

Parameters
eventType: string

Event type to match the handler against

functionUri: string

URI pointing to function when using external event projector.

functions: object[]

The functions to apply for matching events. Will run in specified order

Example
{
  "eventType": "OrderCancelledEvent",
  "functionUri": "https://your-server.com/lambda",
  "functions": [
    {
      "function": "inc",
      "targetSelector": "$.projection.orders[?]",
      "eventSelector": "$.event[?]",
      "targetFilter": "@.orderId == $.event.orderId",
      "eventFilter": "@.orderAmount > 4000"
    }
  ]
}

Function

Parameters
function: string

The name of the function to apply

targetSelector: string

The selector for the target of the function

eventSelector: string

The selector for the event data to use as source

rawData: object

The raw data to use as input to the function, if applicable

targetFilter: string

The target filter determining which state the projection should be for the event to be applied

eventFilter: string

Filter for the events, determining for which events the function should be applied

Example
{
  "function": "inc",
  "targetSelector": "$.projection.orders[?]",
  "eventSelector": "$.event[?]",
  "targetFilter": "@.orderId == $.event.orderId",
  "eventFilter": "@.orderAmount > 4000"
}

Projections

Parameters
projections: object[]
totalCount: integer
Example
{
  "projections": [
    {
      "projectionId": "22c3780f-6dcb-440f-8532-6693be83f21c",
      "createdAt": 1523518143967,
      "updatedAt": 1523518144467,
      "data": "object"
    }
  ],
  "totalCount": 1
}

Projection

Parameters
projectionId: string (uuid)

The id

createdAt: integer

Entry created timestamp

updatedAt: integer

Entry updated timestamp

data: object
Example
{
  "projectionId": "22c3780f-6dcb-440f-8532-6693be83f21c",
  "createdAt": 1523518143967,
  "updatedAt": 1523518144467,
  "data": "object"
}

ReactionDefinitions

Parameters
definitions: object[]
Example
{
  "definitions": [
    {
      "reactionName": "payment-processed-email-reaction",
      "feedName": "payment",
      "reactOnEventType": "PaymentProcessed",
      "cancelOnEventTypes": [
        "OrderCanceledEvent"
      ],
      "triggerTimeField": "my.event.data.field",
      "offset": "PT1H",
      "action": {
        "actionType": "string"
      }
    }
  ]
}

ReactionDefinition

Parameters
reactionName: string

Unique name of the action

feedName: string

Name of the feed

reactOnEventType: string

Event type to react on

cancelOnEventTypes: object[]

Event types to cancel reaction scheduled in the future

triggerTimeField: string

Optional path to event data field containing trigger time. If not specified, trigger time will be ASAP. Dot notation supported.

offset: string

Optional trigger time offset. Defined in the ISO-8601 duration format (PnDTnHnMn.nS). May be negative.

action: Schema
Example
{
  "reactionName": "payment-processed-email-reaction",
  "feedName": "payment",
  "reactOnEventType": "PaymentProcessed",
  "cancelOnEventTypes": [
    "OrderCanceledEvent"
  ],
  "triggerTimeField": "my.event.data.field",
  "offset": "PT1H",
  "action": {
    "actionType": "string"
  }
}

Action

Abstract type

Parameters
actionType: string HTTP_POST, SLACK_POST
Example
{
  "actionType": "string"
}

HttpPostAction

Action issuing a HTTP POST request to given URL.

Parameters
actionType: string
targetUri: string
httpHeaders: object
Example
{
  "actionType": "HTTP_POST",
  "targetUri": "https://your-webhook",
  "httpHeaders": "object"
}

SlackPostAction

Action issuing a HTTP POST request to the given Slack Webhook URL.

Parameters
actionType: string
targetUri: string
body: object
Example
{
  "actionType": "HTTP_POST",
  "targetUri": "https://hooks.slack.com/services/T0000/B0000/XXXX",
  "body": "This as a message to Slack!"
}

ProjectionInfo

Parameters
projectionName: string
feedName: string
aggregated: boolean
projectionsCount: integer
Example
{
  "projectionName": "shipping-stats",
  "feedName": "shipment",
  "aggregated": false,
  "projectionsCount": 1977
}

FeedInfo

Parameters
aggregateType: string
aggregateCount: integer
batchCount: integer
eventCount: integer
Example
{
  "aggregateType": "payment",
  "aggregateCount": 1337,
  "batchCount": 7331,
  "eventCount": 9977
}

Feed

Parameters
entries: object[]
hasMore: boolean

Indicates if there are more events available.

currentSequenceNumber: integer
Example
{
  "entries": [
    {
      "sequenceNumber": 12314,
      "aggregateId": "22c3780f-6dcb-440f-8532-6693be83f21c",
      "timestamp": 1503386583474,
      "events": [
        {
          "eventId": "f2c8bfc1-c702-4f1a-b295-ef113ed7c8be",
          "eventType": "PaymentProcessed",
          "data": {
            "paymentMethod": "CARD",
            "amount": 1000,
            "currency": "SEK"
          },
          "encryptedData": "string"
        }
      ]
    }
  ],
  "hasMore": false,
  "currentSequenceNumber": 123456
}

FeedEntry

Parameters
sequenceNumber: integer
aggregateId: string (uuid)
timestamp: integer
events: object[]
Example
{
  "sequenceNumber": 12314,
  "aggregateId": "22c3780f-6dcb-440f-8532-6693be83f21c",
  "timestamp": 1503386583474,
  "events": [
    {
      "eventId": "f2c8bfc1-c702-4f1a-b295-ef113ed7c8be",
      "eventType": "PaymentProcessed",
      "data": {
        "paymentMethod": "CARD",
        "amount": 1000,
        "currency": "SEK"
      },
      "encryptedData": "string"
    }
  ]
}