Help with auth on POST

I’m trying to get a small script going to enter data for a goal automatically. Everything works just fine, but on all POST requests, I get {"errors":{"message":"Token missing or incorrect token.","token":"no_token"}}. I’ve been alternating between staring at my code and hitting my head against the wall, so any help would be appreciated.

My main source of frustration is that the GET requests to the same resource with the same data work flawlessly.

url = 'https://beeminder.com/api/v1/users/rixx/goals/deficit/datapoints.json'
data = {'auth_token': auth_token}
requests.get(url, data)  # Response 200, all data present

data['value'] = 200
requests.post(url, data)  # 401, {"errors":{"message":"Token missing or incorrect token.","token":"no_token"}}

… Any pointers, please? I must be missing something trivially stupid at this point. I looked at other Python code and it seemed like I’m not doing anything different than anybody else.

Things I tried:
  • Modifying the payload: including more or less data, including unix_timestamp, timestamp etc
  • Attatching the auth_token as a queryparam to the URL
  • Modifying a specific datapoint instead of creating one (same errors)
  • Modifying the auth_token in my get request to make sure it’s used (it is, I get proper 401 on an incorrect token)
  • Short stint with JSON encoded data, just to make sure that’s not it’s not that.

This is Python 3.x with current requests.

2 Likes

Thanks so much for asking when something is confusing even if it’s something dumb! (Not saying it is dumb, but asking even if it might be is very valuable for us in improving the API and the API docs!)

First sanity check: Did you fetch your auth_token from https://www.beeminder.com/api/v1/auth_token.json?

Definitely, yes. I repeatedly checked that I didn’t miss parts of it when retrieving it, and the fact that this token works on GET requests is further evidence that this is the right token.

1 Like

What happens if you add print(data) right before your second requests call?

1 Like

My example was a minimal one – I’ve been printing data and adjusting data all over the place. This issue occurs regardless of the data I send – in this example, the data would be {"auth_token": XXXXXX, "value": 200}.

1 Like

What happens if you try to use this wrapper class with your credentials?

1 Like

I think I’ve figured out what’s going on here.

When I try it, it works just fine if I make the request to https://www.beeminder.com/api/v1/users/me/goals/mygoal/datapoints.json, but fails in the exact way described by @rixx when I make the exact same GET request to https://beeminder.com/api/v1/users/me/goals/mygoal/datapoints.json.

It seems that the apex domain (without www) responds differently than the www.beeminder.com subdomain for some reason or another. This definitely seems to be a bug on Beeminder’s side.

5 Likes

Ohhh, wow, thank you for figuring that out!

1 Like

zzq, I looked at it with curl, and the apex domain is redirecting to the www. subdomain. GETs work fine, but POSTs give a missing token error. (I thought there aren’t any POST redirects in HTTP (that don’t require user intervention) so I’m not sure what a technological fix would look like here.)

To me, the misleading part is that GETs to beeminder.com work fine, so you can go GET your auth token, but then when you do something that needs a POST, you get errors.

We could block the www redirect when it’s going to the API, just giving a 404, which would lead folks to the right place, or I guess we could look for a POST api call without any parameters and give a more human-friendly response.

2 Likes

That makes sense. I had thought of this as a strange and inexplicable bug, but this does indeed explain it.

I think the HTTP status code you’re looking for is 308 (for a permanent redirect, whereas a temporary redirect would be 307.) 308 and 307 are alternatives to 301 and 302 (respectively) that were designed to patch up the flaw with the 301 and 302 status code which meant that the redirected request might be downgraded to a GET.

1 Like

I say just don’t redirect any API calls :man_shrugging:
Don’t accept any on the wrong (sub-)domain. Only at the one documented in the API docs.
No confusion. No problem.

1 Like