Possible to set tags on API goal creation?

Is it possible to apply tags on goal creation? I tried tags=book and tags="[book]" as post params and, at least with dryrun=true, the response had "tags":[] for both attempts :confused:

I don’t see anything on Beeminder API Reference but that also doesn’t mention the description field which the API definitely appears to handle so… I’m not sure I necessarily trust that :stuck_out_tongue:

I found this old forum post but that seems to be asking about receiving tags in the API, which does happen at this point—I just can’t figure out how to create the tags in the first place!

2 Likes

I have never tried to apply tags on goal creation, but this might help…

The syntax below works with Habitica’s API for creating a task that (coincidentally) has a “tags” array. Doing something similar with Beeminder’s API might work.

I.e., you might want tags:["book"] (or = instead of : depending on how you’re sending the API command).

curl -X POST \
    -d '{
        "type": "todo",
        "type": "a task",
        "tags": [
            "tag1",
            "tag1"
        ],
        }' \
    -H "Content-Type: application/json" \
    -H "other stuff...." \
    https://habitica.com/api/...

(Here’s info about Habitica’s API in case it has other useful tips for anyone because it has some fairly generic details about making API calls in a couple of ways. Apologies if this is just useless spam!)

1 Like

Well, the beeminder API documentation doesn’t say anything about accepting JSON at all, so I expected your advice to be unhelpful, @alys, but amazingly

curl -XPOST "https://www.beeminder.com/api/v1/users/rperce/goals.json" \
  -H'Content-Type: application/json' \
  -d '{
    "auth_token": "'"$token"'",
    "slug": "slug",
    "title": "Title (Author)",
    "goal_type": "biker",
    "rate": 0,
    "goalval": 0,
    "gunits": "pages",
    "tags": ["book"],
    "dryrun": true
  }'

actually gets a normal-looking response… that still includes "tags": [] :cry:

@dreev Should I make a new bugabee thread about tags not being settable on creation or is this one enough? :confused:

I guess a small bugabee addition here is that we should probably document that you can totally send json, not just x-www-form-urlencoded. I’m happy to file a PR against beeminder/apidocs if someone official can confirm that that’s actually intentional and ought to be supported/documented :stuck_out_tongue:

1 Like

I’ve just tested, and the update goal endpoint also doesn’t do anything with a tags parameter :frowning:

When I use the Get information about a goal route to fetch the data for a goal that I know has tags on it, the returned data includes "tags":[] – i.e., the tags array is empty. This makes me think that it hasn’t been implemented for the public API (for either adding or fetching goals).

When I look at code in Beeminder’s (private) github repo, the API code for tags is under in a “…/private/…” subdirectory, so I would guess that tags so far have been implemented only for use on the website.

The main bug right now might be that the API docs imply that you CAN fetch and set tags, with the easiest fix being to remove mention of tags from the docs. :slight_smile:

1 Like

Oh FFS, I didn’t even think to verify that the response ever had useful data in the tags array! :man_facepalming:

The API docs don’t imply you can set/fetch tags, but the response kinda does, yeah. If tags are completely nonfunctional from an API perspective, I’d rather see them not included at all rather than included-but-always-empty!

2 Likes

When I use the Get information about a goal route to fetch the data for a goal that I know has tags on it, the returned data includes "tags":[] – i.e., the tags array is empty.

This alarms me, because I have code that actively depends on getting the tags of a goal in the API response. I rushed to try it out—and nope, it seems to work for me.

I ran:

curl -s https://www.beeminder.com/api/v1/users/me/goals/$GOAL.json?auth_token=$TOKEN

And indeed, the response had non-empty tags array (with that goal’s tags.)

The fact that it’s giving you an empty array is weird—I’d like to look into it (and hopefully fix it.) Is there any information you can give me to help replicate it? (Can you double check that the goal you tried it on actually has the tags you expect it to have?)

1 Like

Ah heck. Sorry @rperce tags ARE included in the returned data.

The test I’d been doing yesterday involved a goal that actually DIDN’T have tags, so that’s why the array was empty. When I test now with a different goal, the tags array is populated.

The reason I thought that the goal I used yesterday did have tags was that I first scanned my tags page to confirmed that ALL goals had tags - but then I went and used an archived goal for testing because it was the first one I thought of. Archived goals don’t appear on the tags page so I didn’t see that that goal was missing tags. :scream:

@zzq Thanks heaps for posting!! You’re dead right. :slight_smile:

3 Likes

Guess what? @zzq implemented this for us and it’s live in production now! Can you confirm it works as you expect, @rperce?

http://beeminder.com/changelog#3949

2 Likes

OMG, @zzq, you’re amazing! :heart_eyes:

Hmmm, all of curl ... -d tags=book, curl ... --data-urlencode tags=[book], and curl ... -d tags%5B0%5D=book (that’s tags[0], urlencoded, because --data-urlencode only converts the value side of the key=value pair, for… reasons) resulted in Internal Server Error

but

curl -XPOST "https://www.beeminder.com/api/v1/users/me/goals.json" \
  -H'Content-Type: application/json' \
  -d '{
    ...
    "tags": ["book"]
  }'

totally worked! Mission accomplished, as far as I’m concerned, if we can get “you can set tags if you’re using JSON” in the docs :smiley:

2 Likes

The Rails convention for passing arrays within x-www-form-urlencoded encoded data is to suffix the key with [] (repeating that key multiple times, if the array has multiple elements.) So the thing to do is very similar to what you tried with tags[0]—but the providing the key makes Rails think you’re trying to pass a map, not an array, the equivalent of (in JSON) "tags": { "0": "book" }.

Even curl ... -d tags[]=book should work, if you want to cut corners and skip urlencoding the key, or curl ... -d tags%5B%5D=book if you want to do things properly. Or, you can use JSON, which is probably easier to work with in any case.

2 Likes

Ah, sweet! I think the tags[0] thing is… maybe a PHP thing? Or it lodged incorrectly in my brain at some point. Either way, it looks like tags[]=book (or tags%5B%5D, unsurprisingly) do indeed work: hooray! :smiley:

2 Likes

We think we fixed the 500-errors! Thanks so much, y’all!

http://beeminder.com/changelog#3951

1 Like

Hmm, I’m still seeing 500s for the Wrong Approaches I tried up above. Here’s the full curl for one of them (tags=book):

╔═(robert@erebus)════(~)
╚══~> curl -XPOST "https://www.beeminder.com/api/v1/users/rperce/goals.json" \
          -d auth_token="$token" \
          -d slug="$slug" \
          -d title="$(echo "$title ($author)" | sed 's/ /+/')" \
          -d goal_type=biker \
          -d rate=0 \
          -d goalval=0 \
          -d gunits=pages \
          -d dryrun=true \
          -d 'tags=book'
{"error":"Internal Server Error"}

(I also tested tags[0]=book and tags=[book], each also with urlencoding).

I also saw Internal Server Error for curl ... -H'Content-Type: application/json' '{... "tags": "book"}', so it’s not just the x-www-form-urlencoded handler that’s still 500-ing.

Err, thanks for checking that! I forgot about goal creation, and only updated updates. :man_facepalming:… on it.

1 Like

Ha, that’d do it! Think of it this way: now you get another UVI! :smiley:

Ok, now we really fixed the 500 errors, throughout the API, we think:

http://beeminder.com/changelog#3952

Thanks again for all the help with this!

1 Like

I am trying to update the tags on my goal. I can’t get it to add more than one tag:

Attempt #1: Sending query string parameters

https://www.beeminder.com/api/v1//users/me/goals/fruit.json?tags[]=food&tags[]=nutrition

Behavior: 200, but only saves the last tag in the list

Result: tags: [ 'nutrition' ]

Attempt #2:

    let body = JSON.stringify({
      tags: ['food', 'nutrition'],
    });
    let url = baseUrl + "/users/me/goals/" + slug + ".json";
    let response = await context.fetcher.fetch({
      url: url,
      method: "PUT",
      body: body,
    });

Behavior: 200, but tags don’t change

Result:

tags remains unchanged

Am I doing something wrong?

2 Likes

Yeah, so your first attempt should work, and I can verify with the following curl command:

curl -X PUT http://www.beeminder.com/api/v1/users/USERNAME/goals/GOALNAME.json?auth_token=AUTHTOKEN&tags[]=one&tags[]=two&tags[]=three

checking the logs for the 3rd, I see a bunch of fiddling, trying to get it right, and I don’t see any instances that manage to hit on quite the right syntax with tag[]=thing&tag[]=otherthing

(e.g. there’s tags[]=nutrition,food, and there’s tags[0]=food&tags[1]=nutrition, and tags[][0]=nutrition&tags[][1]=food, and tags[]=food&tags=nutrition etc…)

The second way of doing it should also work, with the tags sent as JSON in the body of the request, and in this instance, I think it’s sort of a combo of some buggy behavior on our end + your tool maybe not doing quite what you think it is doing.

Allow me to attempt to explain myself with curl. Let’s compare the results of the following three commands:

command 1

curl -X PUT http://localhost:3000/api/v1/users/b/goals/fug.json -d "{\"auth_token\":\"THjZxsi1NBmsmA294V_G\",\"tags\":[\"wasp\",\"bee\",\"boson\"]}"

result: 401 unauthorized “Token missing or incorrect token” – erm, wtf?

command 2

curl -X PUT http://localhost:3000/api/v1/users/b/goals/fug.json?auth_token=THjZxsi1NBmsmA294V_G\ -d "{\"tags\":[\"wasp\",\"bee\",\"boson\"]}"

result: 200; no change – in context alongside command 1 result, beeminder is not parsing the json out of the body…

command 3

curl -X PUT http://localhost:3000/api/v1/users/b/goals/fug.json -d "{\"auth_token\":\"THjZxsi1NBmsmA294V_G\",\"tags\":[\"wasp\",\"bee\",\"boson\"]}" -H 'Content-Type: application/json'

result: 200; goal tags are updated

So, when I use my usual go-to ruby http library to test out api commands, it is making assumptions and filling in blanks for me, like setting content-type etc…

Anyway, I’d say Beeminder is not being consistent about how it’s handling content types there, and that bit is rather confusing. I’ll file a bug noting the behavior.

You should be able to set your tags by using the URL params as I showed above, or if you prefer sending the data in the body of the request, just be sure to set the content-type as well.

3 Likes

Yes, I discovered the same . . .

-H 'Content-Type: application/json'

Seems to fix the issue

1 Like