PUT /users/u/goals/g.json should really be PATCH

This endpoint:
http://api.beeminder.com/?shell#putgoal

really behaves as if it was PATCH rather than PUT. In short: PUT puts a complete resource at a given location, whereas PATCH only updates parts of it. Which is what this endpoint is doing.

And, if you actually use the endpoint the way the HTTP method implies it is to be used, that is by supplying a complete goal object in the body, you get this undocumented response:

{"error":"that doesn't look like a road matrix"}
1 Like

And to add insult to injury:

The changes to the goal should really not be set in the same context as all the other parameters, such as the auth_token. Currently, a call (according to the docs) looks like this:

curl -X PUT https://www.beeminder.com/api/v1/users/alice/goals/exercise.json \
  -d auth_token=abc124 \
  -d title=Work+Out+Even+More \
  -d secret=true

Which places the parameter auth_token into the same context or name space as the goal’s attributes title and secret, even though they got absolutely nothing to do with each other.
It is two separate concerns that are mixed here. This is bad design, leads to an unnecessary clash of identifiers and makes coming up with sound static typing unnecessarily difficult.
It makes it so you can never have a goal attribute named auth_token or access_token or any other unrelated parameter that can also be added to this call. And vice versa you can never have any parameter like the auth_token that is of the same name as any of the goal attributes of which there are 81 (!) different ones, including generic sounding ones such as id and slug.

1 Like

I feel conflicted about PATCH, because, as I understand it, the specs don’t want you to just send a partial entity with the fields to be changed. Instead, they want you to send a patch document, which is a description of the changes to be made in an entirely different format. That feels like a lot to expect of casual API users.

2 Likes

I’m not saying there should not be a PUT endpoint, too. I’m just saying the current endpoint pretends to PUT but doesn’t actually PUT. It PATCHes and that’s wrong, confusing and not restful.

Yes and no. PATCH is rather flexible and indeed as you point out, as long as what you are sending is describing changes, some kind of update instructions, you’re fine. There are actually two RFCs, that show how such update instructions could look like: The older and more complex RFC 6902 and the newer and simpler RFC 7396, also known as JSON Merge Patch, which is essentially what the API is doing right now: Only sending the changed fields with their new values. Just as a proper body and not as form parameters. You can read more about both methods in this wonderfully written article:

So, as an example, the body could look like this:

{
  "title": "Work Out Even More",
  "secret": "true"
}

Which is a very simple format. It’s literally a subset of the resource that is to be updated.

1 Like