Search code examples
rubygoogle-people-apiinvalid-argument

Google PeopleApi in Ruby - CreateContact method invalid argument


I'm using the 'google-api-client' gem to connect into Google People API from my Ruby Application. https://github.com/googleapis/google-api-ruby-client

I've managed to get other methods working (list_person_connections, get_people, delete_person_contact and update_person_contact) but I can't get the createContact (create_person_contact) method from google people API to work.

After I send the post, I get this error:

400 Caught error badRequest: Request contains an invalid argument.

This is an example code to create a contact with just the name field (I will want to actually also send email and phoneNumbers parameters on the body, but it also returns the same error, so I'm giving you the simplest example here):

require 'google/apis/content_v2'
require "google/apis/people_v1"
require "googleauth"
require "googleauth/stores/file_token_store"
require "fileutils"
require 'google/apis/people_v1'
require 'google/api_client/client_secrets'

client_secrets = Google::APIClient::ClientSecrets.load 'credentials.json'
auth_client = client_secrets.to_authorization
auth_client.update!(
    :scope => ['https://www.googleapis.com/auth/contacts', 'https://www.googleapis.com/auth/contacts.other.readonly'],
    :redirect_uri => 'http://localhost:3102/oauth2callback',
    :client_id => 'MY CLIENT ID',
    :client_secret => 'MY CLIENT SECRET',
    #:authorization_uri => 'https://accounts.google.com/o/oauth2/auth',
    :additional_parameters => {"access_type" => "offline", "include_granted_scopes" => "true"})
auth_uri = auth_client.authorization_uri.to_s

auth_client.code = 'THE AUTH CODE'
auth_client.fetch_access_token!
people = Google::Apis::PeopleV1::PeopleServiceService.new
people.authorization = auth_client

body = {:names => [{:givenName => "TEST"}]}
people.create_person_contact(body, person_fields: 'names')

The problem is just those 2 last lines. When called, they send this with the body:

Sending HTTP post https://people.googleapis.com/v1/people:createContact?personFields=names

And it returns the error above, no matter what I change. In the documentation, you can actually try and test this exact same code and it works.

https://developers.google.com/people/api/rest/v1/people/createContact?authuser=2&apix=true&apix_params=%7B%22personFields%22%3A%22names%22%2C%22resource%22%3A%7B%22names%22%3A%5B%7B%22givenName%22%3A%22TEST%22%7D%5D%7D%7D

You can fill the request body form exactly as I did, and hit EXECUTE And it will give a 200 OK response.

I can't see what the invalid argument is. This is also exactly what I do on the update_person_contact method and that one works.

I've searched the internet and can't find anyone with a similar problem and the documentation just doesn't say much: https://www.rubydoc.info/github/google/google-api-ruby-client/Google%2FApis%2FPeopleV1%2FPeopleServiceService:create_person_contact

Anyone have any idea to help me? Thank you.


Solution

  • After almost giving up, I decided to try the CURL option. So I copied it from their 'Try this API' page I linked above and translated it to Ruby code.

    curl --request POST \
      'https://people.googleapis.com/v1/people:createContact?personFields=names' \
      --header 'Authorization: Bearer [YOUR_ACCESS_TOKEN]' \
      --header 'Accept: application/json' \
      --header 'Content-Type: application/json' \
      --data '{"names":[{"givenName":"TEST"}]}' \
      --compressed
    

    And you know what? It worked.

    So I think this gem doesn't work for this particular case (it is google-api-client v: 0.42.2 and 0.43.0 in case you are wondering), but if you came here to find a solution to the same problem, this is what worked for me, and I hope it helps you:

    (this replace those last 2 lines on my code):

    require 'net/http'
        require 'uri'
        require 'json'
    
        uri = URI.parse("https://people.googleapis.com/v1/people:createContact?personFields=names")
        request = Net::HTTP::Post.new(uri)
        request.content_type = "application/json"
        request["Authorization"] = "Bearer #{people.authorization.access_token}"
        request["Accept"] = "application/json"
        request.body = JSON.dump({
                                     "names" => [
                                         {
                                             "givenName" => "TEST"
                                         }
                                     ],
                                     "emailAddresses" => [
                                         {
                                             "value" => "[email protected]"
                                         }
                                     ],
                                     "phoneNumbers" => [
                                         {
                                             "value" => "12345678"
                                         }
                                     ]
                                 }
        )
    
        req_options = {
            use_ssl: uri.scheme == "https",
        }
    
        response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
          http.request(request)
        end
    
        response.code
        response.body
    

    It's not ideal, but it got the job done today.

    EDIT: After writing this I just realized even the 'personFields' parameter is useless, since the body got the right fields.

    You can see in my answer, I only called the 'names' fields on the URI, but all those 3 fields were correctly there on my new contact (name, email and phone number) after it got saved. So that's also probably useless/optional.