Creating badge via API query works, but returns 422

I want a way to make groups of badges:

  • bronze -> submitted with certain tag
  • silver -> submitted tag, liked by me
  • gold -> submitted tag, liked by me and 3 other people

I need to make a bunch of them and it’s tedious doing it from the web interface. One day I’ll write a plugin, but until then, I thought I’d do a quick Python script.

I had given up, as it fails with

urllib.error.HTTPError: HTTP Error 422: Unprocessable Entity

but when I glanced again at the badges admin page, I found that my badge had indeed been created. I guess maybe I don’t care, as it does work, but any ideas on why I get this error?

I added a bunch of headers thinking that might somehow help. It didn’t seem to (but they don’t seem to have hurt, either).


from urllib.request import Request, urlopen
from urllib.error import URLError
import urllib.parse
API_USERNAME = 'pfaffman'

url = ''

values = {'allow_title' : 'true',
          'multiple_grant' : 'true',
          'listable' : 'true',
          'auto_revoke' : 'false',
          'enabled' : 'false',
          'show_posts' : 'true',
          'target_posts' : 'true',
          'icon' : 'fa-certificate',
          'image' : '',
          'name' : BADGE,
          'description' : 'testing 1, 2, 3',
          'query' : """SELECT p.user_id, min(p.created_at) granted_at, MIN( post_id
FROM badge_posts p
JOIN topics t ON = p.topic_id
JOIN topic_custom_fields tcf on = tcf.topic_id
JOIN post_actions pa ON pa.post_id = AND 
      post_action_type_id = (
                SELECT id FROM post_action_types WHERE name_key = 'like'
       ) AND 
       pa.user_id IN (
           SELECT gu.user_id
           FROM group_users gu
           WHERE gu.group_id = ( SELECT id FROM groups WHERE name ilike 'Leader' ) 
WHERE category_id = ANY (
  SELECT id FROM categories WHERE name ilike '%completions%'
) AND p.post_number = 1
AND p.like_count > 0
AND LIKE 'tags' and tcf.value LIKE '%wordpress-basics%'
and (:backfill OR ( IN (:post_ids) ))
GROUP BY p.user_id
'badge_grouping_id' : '7',
'trigger' : '2',
'badge_type_id' : '1',
'api_username' : API_USERNAME,
'api_key' : API_KEY

headers = {'content-type' : 'application/x-www-form-urlencoded; charset=UTF-8',
           'x-requested-with' : 'XMLHttpRequest',
           'referer' :'',
           'origin' : '',
           'user-agent' : 'discourseBadgeCreator',
           'referer' : '',
           'content-type' : 'application/x-www-form-urlencoded; charset=UTF-8'}

data = urllib.parse.urlencode(values)
data = data.encode('ascii') 
req = urllib.request.Request(url, data, headers)

print("\n\nvalues: ", data)

try: urllib.request.urlopen(req)
except URLError as e:    
    print ("\n\n--------------------YO!--------------------\n\n" , e.reason)
    print ("\n\nHeaders:\n\n ", e.headers)

with urllib.request.urlopen(req) as response:
    if response.code == '200':
        print ("It worked!")
        print ("Darn.")

You get this error if you try to create a badge that has a name that already exists.