Getting 'Missing required field: member' when trying to add a member to a google group via API
Question: Trying to use Google admin directory API in order to read members of a google
group (organization) - it works fine. When I try to add a member I get:

    
    
    { errors: 
       [ { domain: 'global',
           reason: 'required',
           message: 'Missing required field: member' } ],
      code: 400,
      message: 'Missing required field: member' }
    

I've googled the error and found questions like
[this](http://stackoverflow.com/questions/22765599/missing-required-field-
member), [this](http://stackoverflow.com/questions/27057265/google-groups-
directory-api-add-user-to-group-raises-error-php) and a few other unhelpful
results.

I checked and it's definitely _not_ a missing scope nor permissions.

    
    
    #!/usr/bin/python
    import httplib2
    import json
    from oauth2client.client import SignedJwtAssertionCredentials
    from urllib import urlencode
    
    
    def get_group_members(group):
        url = 'https://www.googleapis.com/admin/directory/v1/groups/{}/members'.format(group['email'])
        return call_google_api("GET", url)
    
    
    def add_group_member(group, payload=False):
        url = 'https://www.googleapis.com/admin/directory/v1/groups/{}/members'.format(group)
        return call_google_api("POST", url, payload)
    
    
    def call_google_api(method, url, payload=False):
        content = {}
        try:
            http = get_conn()
            if payload:
                (resp, content) = http.request(uri=url, method=method, body=urlencode(payload))
            else:
                (resp, content) = http.request(uri=url, method=method)
        except Exception as e:
            print "Failed to post request to [{}] due to: {}".format(url, e)
        return json.loads(content)
    
    def get_conn():
        client_email = get_client_email_from_db()    
        with open(get_private_key_filename()) as f:
            private_key = f.read()
    
        oauth_scope = ['https://www.googleapis.com/auth/admin.directory.group.member', 
                      'https://www.googleapis.com/auth/admin.directory.group',
        ]
    
        credentials = SignedJwtAssertionCredentials(client_email, private_key, oauth_scope, sub='googleapi@organization.com')
        http = httplib2.Http()
        return credentials.authorize(http)
    
    
    if __name__ == '__main__':
        payload = {
            "email": "test-user@organization.com",
            "role": "MEMBER",
        }
        print "\n ---------------------------------- \n"
        print "calling add_group_member('test-user@organization.com', 'test-group@organization.com')"
        res = add_group_member("test-group@organization.com", payload)
        print "\n ---------------------------------- \n"
    

**Comment** :  
I managed to achieve what I wanted by using the sdk
`apiclient.discovery.build`, but still - I'm curious, what's the issue and if
it can be solved.

Debugging the request:

    
    
    connect: (www.googleapis.com, 443)
    send: 'POST /admin/directory/v1/groups/xxxx@xxxx.com/members HTTP/1.1\r\nHost: www.googleapis.com\r\nContent-Length: 38\r\ncontent-type: application/json\r\naccept-encoding: gzip, deflate\r\nauthorization: Bearer ya29.RAFzf3hyxvP0LuR4VdpqKr_dD0WzOcvXjn4eWV5Em6xJDissi4ieOZ2ZBRMOP-WLhvTrecBxgF_6sznc1GKSWHanvgYTh_EzcilsAN0f5jOiiMahOadG2v5ixBPL9GcqebRdz_kQc1y2iQ\r\nuser-agent: Python-httplib2/0.9 (gzip)\r\n\r\nrole=MEMBER&email=alfasi%40xxxx.com'
    reply: 'HTTP/1.1 400 Bad Request\r\n'
    header: Vary: Origin
    header: Vary: X-Origin
    header: Content-Type: application/json; charset=UTF-8
    header: Content-Encoding: gzip
    header: Date: Sat, 28 Mar 2015 23:14:47 GMT
    header: Expires: Sat, 28 Mar 2015 23:14:47 GMT
    header: Cache-Control: private, max-age=0
    header: X-Content-Type-Options: nosniff
    header: X-Frame-Options: SAMEORIGIN
    header: X-XSS-Protection: 1; mode=block
    header: Server: GSE
    header: Alternate-Protocol: 443:quic,p=0.5
    header: Transfer-Encoding: chunked
    


Answer: Since google APIs use (only?) JSON encoding, your post data is not being
parsed into the needed member object. You are already loading json for the
response, so you should just need to change the encoding, and optionally
indicate it explicitly:

    
    
     if payload:
            (resp, content) = http.request(uri=url, method=method, body=urlencode(payload))
     # becomes:   
     if payload:
            (resp, content) = http.request(uri=url, method=method, body=json.dumps(payload), headers={'Content-type':'application/json'})
    

