What is AS2?

All right. You have set up your local stations and trading partners on AS2 Gateway B2B Trading Platform - and successfully sent and received messages. Today, let's see how we can automate these AS2 communications - using the brand new AS2 Gateway REST API!

Of course, if you haven't set up AS2 communications yet, you can always get started right away, for free.

I'll be using curl, so I can show you the whole story - URL, headers, payload formats and all. But you can use any tool (say, Postman) to follow along; and use whatever language or library (HttpClient, requests, axios - to name a few) when it comes to programmatic automation!

Authorization

AS2 Gateway REST API is secured with token-based auth, so the first thing you need is an auth token.

curl -XPOST https://api.as2gateway.com/v1/authorize \
    -H 'Content-Type: application/json' \
    --data '{"username":"email@domain.com","password":"pazzword"}'

Replace email@domain.com and pazzword with your actual AS2G account credentials.

The response would be like:

{
    "token": "hereGoesTheLongLongLongLongToken",
    "expiry": 1574299310779
}

Extract out the token field. This would be valid until the time indicated by the expiry timestamp - usually 24 hours. You can reuse the token until then, saving yourself the trouble of running auth before every API call.

Send a Message!

Good! We have the token, so let's send our message!

curl -v -XPOST https://api.as2gateway.com/v1/messages/AWSMSTTN/AWSMPTNR \
    -H 'Authorization: hereGoesTheLongLongLongLongToken' \
    -H 'Content-Type: multipart/form-data; boundary=----foobarbaz' \
    --data-binary \
'------foobarbaz
Content-Disposition: form-data; name="file"; filename="file1.txt"
Content-Type: text/plain

one
------foobarbaz
Content-Disposition: form-data; name="file"; filename="file2.txt"
Content-Type: text/plain

two
------foobarbaz--'

True, this is a bit too much for curl; obviously you would use a more convenient way - File option of Postman, MultipartEntityBuilder for Apache HttpClient, and so on. But the bottom line is:

You specify the AS2 IDs of your origin (local trading station) and destination (remote trading partner) as path parameters - on the API call URL
You can optionally include a message subject as a query parameter
As the request body (payload) you compose and send a multipart request] - including the boundary as a `Content-Type` HTTP header on the API call request
You can include multiple files (attachments) in your AS2 message by including as many "file" parts as needed, in the multipart body; each with a unique filename attribute.

Looking at the -v trace:

> POST /v1/messages/AWSMSTTN/AWSMPTNR HTTP/1.1
> Host: api.as2gateway.com
> User-Agent: curl/7.47.0
> Accept: */*
> Authorization: hereGoesTheLongLongLongLongToken
> Content-Type: multipart/form-data; boundary=----foobarbaz
> Content-Length: 243
>

* upload completely sent off: 243 out of 243 bytes

< HTTP/1.1 202 Accepted
< Date: Wed, 20 Nov 2019 02:53:25 GMT
...
< Link: https://api.as2gateway.com/v1/messages/sent/<0123456789.012.1574218406002@as2gateway.com>
< Content-Type: application/json
< Transfer-Encoding: chunked
<

* Connection #0 to host api.as2gateway.com left intact

{"message":"Successfully added a new outbound entry"}

The response would be an HTTP 202 (Accepted), with:

{"message":"Successfully added a new outbound entry"}

Remember to save up the response HTTP headers too: we're gonna need them later.

Cool! So our AS2 message was sent out?

No. Not yet.

"Queued", "Sent", and "Failed"

When AS2G sent you that 202 response, it meant that it has accepted the challenge of sending your files to AWSMPTNR. So the message is now enqueued for delivery.

Within about 5 seconds, AS2G will attempt to send your message out to AWSMPTNR, based on the URL, certificates, etc. that you have configured on their partner configuration.

(If the send fails, it will automatically retry in 10s; then 20s; then 40s; and so forth, up to 10 times.)

So, after you call the message send API, the message could end up in one of three places:

If AS2G has not yet tried to send the message - or has tried, failed and is planning to try again - it would appear under Queued.
If AS2G successfully sends it out, it would appear under Sent.
If the send fails, it will go under Failed. Also, as mentioned before, depending on the nature of the failure (e.g. if it is retryable - such as a temporary network issue) it may continue to appear under Queued as well.

So, in order to check what happened to the message, we better check under Sent first - we all love happy-day scenarios, don't we?

Checking Under Sent

curl 'https://api.as2gateway.com/v1/messages/sent/<0123456789.012.1574218406002@as2gateway.com>' \
    -H 'Authorization: hereGoesTheLongLongLongLongToken'

Looks fine: GET the message under sent, with that particular ID. But how do you get the ID?

Remember the response headers we saved up from the send API call? In there, there is a Link header, containing not just the message ID - but the entire sent-message URL!

Link: https://api.as2gateway.com/v1/messages/sent/<0123456789.012.1574218406002@as2gateway.com>

You can directly call that URL (adding the auth header) and get back an AS2 Message entity representing the sent-out message:

{
    "as2MessageId": "<0123456789.012.1574218406002@as2gateway.com>",
    "persistedTimestamp": 1574218406002,
    "compressed": true,
    "encrypted": true,
    "signed": true,
    "subject": "AWSMPTNR",
    "receiverId": "AWSMPTNR",
    "senderId": "AWSMSTTN",
    "transportStatusReceived": 200,
    "deliveryStatus": "Delivered",
    "mdnStatus": "Received",
    "partnerType": "Production",
    "mdnMessage": {
        "persistedTimestamp": 1574218406100,
        "mdnError": false,
        "content": "MDN for Message-ID: <0123456789.012.1574218406002@as2gateway.com>\r\n\
From: AWSMSTTN\r\nTo: AWSMPTNR\r\nReceived on: Wed Nov 20 02:53:26 UTC 2019\r\n\
Status: processed\r\n\
Comment: This is not a guarantee that the message has been completely processed or \
understood by the receiving translator\r\n\
Powered by the AdroitLogic UltraESB-X (https://www.adroitlogic.com)\r\n"
    },
    "attachments": [
        {
            "name": "file1.txt",
            "size": 3
        },
        {
            "name": "file2.txt",
            "size": 3
        }
    ]
}
If the message got an MDN back, it would also be included - under the mdnMessage field.
Also, the transportStatusReceived field represents the actual HTTP response code AS2G got back when sending out the message. It may become handy, say, when troubleshooting a missing MDN - knowing what we got back from the actual send-out HTTP call.

In this case, transportStatusReceived is HTTP 200 - and we have successfully received a non-error MDN ("mdnError": false); voilĂ !

Checking Under Failed

If your message was not so lucky - i.e. it failed to get sent - a copy would end up under failed:

curl 'https://api.as2gateway.com/v1/messages/failed/<0123456789.012.1574218406002@as2gateway.com>' \
    -H 'Authorization: hereGoesTheLongLongLongLongToken'
{
    "as2MessageId": "<0123456789.012.1574218406002@as2gateway.com>",
    "persistedTimestamp": 1574218406002,
    "compressed": true,
    "encrypted": true,
    "signed": true,
    "subject": "AWSMPTNR",
    "receiverId": "AWSMPTNR",
    "senderId": "AWSMSTTN",
    "transportStatusReceived": 404,
    "deliveryStatus": "Not Delivered",
    "mdnStatus": "Pending",
    "partnerType": "Production",
    "attachments": [
        {
            "name": "file1.txt",
            "size": 3
        },
        {
            "name": "file2.txt",
            "size": 3
        }
    ]
}

Almost same as Sent, except for the path fragment change. You can derive the URL easily from the Link header described above.

Note that some messages fail one-time, but others can keep on retrying and failing - in the latter case, there could be multiple entries under failed with the same message ID; but the API will always return the most recent one.

Checking Under Queued

If the message doesn't appear under either of the above - say, after 10 seconds from the send call - AS2G might not have gotten a chance to try to send it out. If so, it could be still in the queue:

curl 'https://api.as2gateway.com/v1/messages/queued/<0123456789.012.1574218406002@as2gateway.com>' \
    -H 'Authorization: hereGoesTheLongLongLongLongToken'
{
    "as2MessageId": "<0123456789.012.1574218406002@as2gateway.com>",
    "persistedTimestamp": 1574218406002,
    "compressed": true,
    "encrypted": true,
    "signed": true,
    "subject": "AWSMPTNR",
    "receiverId": "AWSMPTNR",
    "senderId": "AWSMSTTN",
    "partnerType": "Production"
}

Note that, while you checked sent and failed and decided to check queued, AS2G may have started to send the message. In that case it may not appear under queued as well - because we don't currently expose "retry-in-progress" messages via the queued endpoint.

Bottom Line: Checking Sent-out Message Status

Call the send API.
Give AS2G a few seconds - ideally 10-20 seconds - so it can try to send the message once.
Check sent ( Link header from send call). If the message is there, all went well.
If message is not in sent, check failed. If it is there, the send-out has failed.
If both endpoints don't have the message, AS2G is probably busy (it has not had a chance to process your message).
Check queued , after a few seconds. If you see the message, it has probably failed once - and an entry should now be there under failed .
If queued doesn't have the message, check sent and failed again - just to make sure.
If it is still missing, repeat the queued-sent-failed check after a few seconds' delay.
Unlikely but possible (if you are really unlucky): if the message remains missing after several such tries, something has gone wrong in AS2G itself; shout out for help.

There's More!

Cool! Now you can send out AS2 messages via the AS2G REST API - and ensure that it actually got sent out, check the received MDN, and so forth.

But the API goes way beyond that:

download actual MDN for a sent message
stop/resume retrying of a queued message
check received messages: GET /messages/received - with several filters
download attachments of a received message
mark/unmark a received message as "read" - so you won't see it again in the received messages listings
list sent, queued and failed messages - similar to /received

We are constantly working on improving the API - so, by the time you read this, there may be a lot of other cool features in the API as well; check our API docs - also available as a PDF - for the complete and latest updates!

In Closing

AS2 Gateway makes it pretty easy to manage your B2B document exchange.

So far AS2G supported SFTP - and custom mechanisms for the On-Premise version - as integration points.

But now, with the REST API, it all becomes way much easier!

Right now, the REST API is available for all AS2G customers, at no extra cost.

But the best news is, it is fully available - along with all the other premium features - during the 30-day, extensible free trial!

So check it out, try it out, and tell us what you think!

Good luck with all your B2B communications!