2023-07-25

Royal Mail API (RMAPI v4)

We have used Royal Mail for postage for some time. They had an XML API which we have used, and it works.

What is interesting is how all of these APIs are moving from XML to JSON now. One of the big benefits of JSON is none of the FUCKING XML NAMESPACES (sorry, did I say that out loud?).

Even so JSON has its issues, but nothing like XML with namespaces.

Manuals

They have a web site with a login and loads of interactive stuff, and that includes the API and API manuals. They also have a "V4 Shipping API Consolidated Guide" PDF they sent. So how hard could it be. I had two manuals!

To put this in context, I am someone that has used (and written) many APIs that are JSON/http based over the years. I practically invented the concept (I even have a patent on form posting from over 30 years ago). I have some clue, honest.

I actually quite like the latest "web" based stuff with JSON sent and received. Even OAUTH crap. I have some experience with this, honest.

Update: Before logging in there are some extra links, and another set of manuals, which is yet again different and contradictory - arrrg!

Authentication

First challenge is authentication, and to some extent the manuals were not that bad. The one critical thing they could have done is include, in any of the manuals, one simple example.

They use OAUTH2 but in a way I have not seen anyone else use. I needed a POST to a URL with a URL encoding post of grant_type=client_credentials (and it had to be a POST not a GET) using Basic authentication of the client ID and key they allocated. This is an unusual way to OAUTH2, but valid, to my huge delay of some hours getting the hang of it was really down to me. I get back a Bearer key with expiry (1 hour).

API URL

One issue is the URL, well, the hostname. The documents state that the hostname to use is for their TEST system. This is good, they have a test system, but the other manual suggests it is the hostname for the LIVE system. Why?

I eventually worked it out, there is one hostname for authentication, and whether it is test or live depends on your account. Your account can be in "sandbox". I mean that is great, a good system, but why the fuck not state that in either of the manuals?

What adds to the fun is that hostname is actually only to authenticate. The actual hostname for the service is different, and searching both manuals I do not see the actual hostname for actual API calls listed anywhere.

Why? WTAF?

JSON blob

The big clue was some swagger.json file you can download. Loads of JSON, some "OpenAPI" thing. That has been way more helpful than either of the manuals!

It explains the actual hostname to use for the API, and each of the schemas for each API.

The manual, well one of them, lists fields you need, but omits that these may or may not be in sub objects. The JSON blob explains in way more detail.

And, of course, this JSON file, whilst really good, is missing a load of things, like creating manifests!

Errors

For example, the error "Could not find member 'ContactName' on object of type 'Destination'. Path 'Destination.ContactName'" fooled me for a while as I was supplying Destination.ContactName. What it meant is I should not be supplying that. I read "Count not find" as I was missing something, but no, it meant I had supplied something it "could not find" a use for. That is shit UI. (FYI I should have provided Destination.Address.ContactName)

Tracking

There is, of course, tracking. There is an API to get tracking and an option to have tracking posted to a web hook - yay!

But the documentation for the tracking API just says the response is a tracking number? Which, err, makes no sense, what of the status of the shipment. Hmmm.

And apparently the tracking web hook is not supported, so why the hell is it in the API documentation? Arrrg!

Working

I have it working now - but this is literally one of the worst documented APIs ever.

The raw JSON file was more documentation than either if the manuals, but even that is missing bits.

Icing on the cake

Royal Mail have What3Words embedded. I kid you not.

This is so mental! RM have PAF which has detailed (like, to 10cm) delivery point details on all UK addresses. They are the one organisation that has ZERO use for W3W.

I don't know what they do with it - I will ask?

  • If a W3W supplied is way off, like hundreds of miles, do you use it?
  • If a W3W is next door to postal address provided, do you use it?
  • If a W3W is within target address, e.g. a shed in garden, do you use it?

If all are "no", I have to ask WHY THE FUCK it exists in their API!

[Update: Answer is they don't use the W3W filed.... So WTF have it?!?!]

6 comments:

  1. FUCKING XML NAMESPACES
    FUCKING XML NAMESPACES
    FUCKING XML NAMESPACES

    Sorry, I thought that was so justifiable on your part that it deserved repetition.

    Particularly hilarious is that the only useful way to navigate XML except via really tiresome tree APIs, XPath, *requires* XML namespaces to work even though almost every document it is applied to is sufficiently small that just allowing no namespaces is the obviously right thing to do. But try using XPath on such a document and, no, of course you can't leave all the namespaces out, it just returns nothing every time if you do that! You have to put in pointless, verbose, useless crappy namespace: nonsense in front of *absolutely bloody everything* before XPath will work at all. WHY WHY WHY?

    (Well, the obvious reason is that everything related to all but the very earliest days of XML was ultra-corporate and overdesigned for immense documents which frankly hardly ever needed namespaces either unless they were bodged together by combining other documents in gross fashion. Even then you had to worry about people using the *same namespace prefix* in all combined documents, so namespaces didn't actually buy you a single bloody thing! You had to scan across the lot and do renaming passes anyway.)

    ReplyDelete
  2. Another bit -- the errors look to me like the banking thing that credit/debit are from the bank's perspective: in this case, the error is possibly from the perspective of something looking up everything you provided on some internal object and expecting to find a match. So they look up Destination.ContactName on that object and, oops, no match! Could not find member! On an internal object you never see. (If they did do it this way, one wonders if they report *missing* fields at all.)

    Software developers suck at errors. (We suck at APIs, too, speaking as someone who just found an irremediable error in an API of his own. Can't fix it, the API is stable: all I can do is add a better API, and now there are *two* choices, apparently redundant except that one works and the other has subtle bugs: wonderful.)

    ReplyDelete
  3. "and now there are *two* choices, apparently redundant except that one works and the other has subtle bugs" - it sounds like your assimilation into Microsoft has started ...

    ReplyDelete
    Replies
    1. I will not be Microsoft until I name a function with 'Ex' on the end. (But really, naming this sort of "whoops" function is a hard problem indeed. You already used the good name for the function you can't change...)

      Delete
  4. When I first came across XML back in the naughties, I thought it was awesome. Then I started using it in anger and discovered the reality. I was glad to discover YAML/JSON.

    ReplyDelete
  5. And I thought I was the only one who thinks that the RM v4 API documentation is atrocious ...

    No example for curl in the docs for authentication ... (shakemyhead) is a shame no one feels generous enough to post a curl example

    ReplyDelete

Comments are moderated purely to filter out obvious spam, but it means they may not show immediately.

Fencing

Bit of fun... We usually put up some Christmas lights on the house - some fairy lights on the metal fencing at the front, but a pain as mean...