Messaging Pattern

The fundamental core of the Connect API is built on asynchronous messaging, which now offers options for parallel processing and various strategies to enhance your integration. You can think of the client message container as an inbox. The client initiates by sending a request to the server and then periodically checks the inbox for a response. If there are any messages in the inbox, the default behaviour is to return the oldest unread message.

The lifecycle of a single message encompasses three stages:

  1. Sending the request

  2. Retrieving the response

  3. Deleting the response.

This is illustrated below:

A typical flow of API requests for payment and account-statement messages respectively:

POST [base-url]/payment                 # submit payment request
GET [base-url]/messages/next            # get response message with first payment status
# process message on customer side
DELETE [base-url]/messages/[Message-Response-Id]    # confirm message received

POST [base-url]/account-statement       # submit account statement request
GET [base-url]/messages/next            # get response message with account statement data status
# process message on customer side
DELETE [base-url]/messages/[Message-Response-Id]    # confirm message received

Idempotency Keys

Idempotency keys are an optional feature that allow you to ensure that your message request is processed at most once. This means you will not risk Connect acting on your message request twice if you retry an HTTP request due to a network interruption. Any such duplicate will be harmlessly rejected.

Idempotency keys are an X-Idempotency-Key header that you add to your HTTP request. If present, the header value must be a UUID, generated uniquely for each unique message request. For example

X-Idempotency-Key=bfce988a-1bc1-47fc-93d6-a5b8115cea64

The above example was generated by UUID.randomUUID() in Java (from java.util.UUID). Similar functions can be found in virtually any programming language, often as part of the standard library. No particular version of UUID is required - any standard form is accepted (case insensitively)

Connect will accept the first HTTP request with this idempotency key, but if another request with the same key is received, it will instead reject the message with an HTTP 409 (CONFLICT) status. This is an error code, and does mean something has gone wrong somewhere, but it also means that a previous request did succeed, so Connect has received your message fine.

Connect is guaranteed to detect and reject duplicate idempotency keys with up to 24 hours between them. In practice, it may detect those even further apart, but this should not be relied upon.

Idempotency keys should never be reused, even days apart, even for requests to different endpoints. The only reason that two HTTP requests should use the same key is if one is a retry of a failed request. For fresh requests, concerning a new message, you must generate a new UUID each time. As long as you use a standard UUID-generating function, you do not have to worry about duplicates being generated

Detailed Logic

In most cases you do not need to implement any logic by hand, as most HTTP client libraries will let you declaratively ask for retries, similar to the following pseudocode.

# This is not real code
def make_message_request(endpoint, body):
    idempotencyKey = generate_uuid()
    httpClient.post(
        endpoint,
        body,
        headers={ "X-Idempotency-Key": idempotencyKey },
        retryLimit=3,
    )

But for the purposes of illustration, this is the full logic that should result.

def make_message_request(endpoint, body):
    idempotencyKey = generate_uuid()
    for attempt in range(0, 3):
        try:
            httpClient.post(endpoint, body, headers={ "X-Idempotency-Key": idempotencyKey })
            return # Success
        except NetworkException as e:
            # Request failed
            log(e)

Observe that the same idempotency key may be sent multiple times. This is because all of those HTTP requests belong to one logical message request. In contrast, a new message request will get a new idempotency key.

Last updated