Generating Clients/SDKs Using Swagger Codegen

Time marches on! This article is now out of date. Please read Generating Client SDKs for the Looker API for the latest instructions for building the Looker API client SDK for your programming language.


The Looker API v3.0 has a custom authentication scheme which requires a SHA-1 hash of the query parameters. Does the generated code know how to do this or I need to modify the generated code.


The Swagger-generated code should provide the necessary methods to authenticate without any further effort or encryption. Based on my experience with Java and Python SDKs generated from Swagger, it’s as straightforward as the example above.

I’ll also mention that our API documentation on is out of date, so ignore this document if you’re using API 3.0.


OK. I’m using API 3.0 and creating a .NET SDK. I thought I could gen it from Swagger Code Gen. That looks like it will work. I’ll test it out.


So that means that I don’t have to worry about adding the SHA-1 signature and nonce, etc to the HTTP request, right?


As far as I know, there’s no way to generate a .NET SDK using Swagger Codegen. Rather than write your own SDK from the ground up, you might consider generating something in Java, then use something like jni4net as a means calling Java from .NET.

As for the SHA-1 signature from the docs. I believe our authentication scheme has changed (simplified) quite a bit, so you can ignore that most likely. If, however, you go down the path of writing your own SDK for API 3.0 from the ground up, you may want to take a look at our Ruby SDK or some Swagger-generated SDK for guidance on that.

Thanks for the help. Swagger Gen does support C# and .NET. I’ve generated the classes. I’ll test them this weekend and update this discussion on my progress.

Thanks for your help.


Can I get a sample of a valid HTTP request for a request (not Login). I’ll need the HTTP headers, Body, and Parameters. A simple example would be Logout and GetUser.

I have login in working. I suspect that is because it only requires ClientId and Secret. However, on subsequent calls like logout or get user I will get HTTP 401 - Requires Authentication. I suspect I’m NOT sending the HTTP headers over properly (Authorization, etc)


I found what I was looking for at Ruby SDK Authentication Implementation. As the Looker documentation is out of date, this serves to resolve my issues.

I was able to get the Swagger Codegen to generate the C# .Net implementation of the client. It’s important to note that I had to add the authorization token to the Authorization header parameter. And add it to the default header (see below).

`    class Program
        static void Main(string[] args)
            string clientId = "client id";
            string clientSecret = "secret";

            IO.Swagger.Api.ApiAuthApi authApi = new IO.Swagger.Api.ApiAuthApi();
            AccessToken token = authApi.Login( clientId, clientSecret);

            // set the default authorization header to 'token <your token>'
            // this will add as a default header and be sent on all API calls
            ApiClient client = authApi.ApiClient;
            client.AddDefaultHeader("Authorization", "token " + token.Token);

            UserApi userApi = new UserApi(client);
            User meUser = userApi.Me("first_name,last_name, email");

            string output = authApi.Logout();
1 Like

Not being familiar with using OAuth 2.0 and curl, the setup steps to get swagger.json took a bit of figuring out.
In case anyone else is experiencing similar difficulties:

  1. Get the access token:
    curl -X POST -d ‘client_id=Pxg…&client_secret=sdfo…’
    -> returns {“access_token”:“bhg5…”,“token_type”:“Bearer”,“expires_in”:3600}
  2. Use the access token to get the resource of interest
    curl -H ‘Authorization: Bearer bhg5…
    -> returns swagger.json

(Possibly optional Step 0: some fiddling with ca-cert location on Ubuntu to get curl https working:
sudo ln -s /etc/ssl/certs/ca-certificates.crt /etc/pki/tls/certs/ca-bundle.crt
but that could be machine-specific)

1 Like

Thanks for the excellent article! I was able to generate and install the python client library using your directions. I modified your sample code to call looks.all_looks(), but it returns a 404 error. The user who’s API 3 client id/secret I’m using has Admin role. See below for the stack trace.

Not sure if I need to supply some parameter to the call or what, any help would be appreciated.

Traceback (most recent call last):
File “”, line 25, in
lookList = looks.all_looks()
File “/Users/scottdavidson/looker_python_client/swagger_client/apis/”, line 121, in all_looks
File “/Users/scottdavidson/looker_python_client/swagger_client/”, line 322, in call_api
response_type, auth_settings, callback)
File “/Users/scottdavidson/looker_python_client/swagger_client/”, line 149, in __call_api
post_params=post_params, body=body)
File “/Users/scottdavidson/looker_python_client/swagger_client/”, line 342, in request
File “/Users/scottdavidson/looker_python_client/swagger_client/”, line 184, in GET
File “/Users/scottdavidson/looker_python_client/swagger_client/”, line 177, in request
raise ApiException(http_resp=r) (404)
Reason: Not Found
HTTP response headers: HTTPHeaderDict({‘Vary’: ‘Accept-Encoding’, ‘Content-Type’: ‘application/json;charset=utf-8’, ‘Content-Length’: ‘69’, ‘X-Cascade’: ‘pass’, ‘X-Content-Type-Options’: ‘nosniff’})
HTTP response body: {“message”:“Not found”,“documentation_url”:“”}


Did other methods for manipulating Looks workd?

If not, do you happen to have a port in your Looker endpoint—e.g., If so, did you also put that port in your api endpoint? If so, perhaps drop that port and try the procedure again.

Let me know.

Didn’t try other looks methods…need a look ID for the other and all_looks() appeared to be the most basic. Any others you suggest I try?

When I change the port in the python script from 19999 to 9999 the call to login fails with a 403 error. Not sure what you mean by “put that port in your api endpoint”.

From what I’ve gathered from your article API communication is over 19999, but typical Looker traffic is over 9999. Or am I misunderstanding?


Try dropping the port altogether from the API endpoint.

login can’t even connect when I drop the port:

2016-02-23 12:59:28,969 WARNING Retrying (Retry(total=2, connect=None, read=None, redirect=None)) after connection broken by ‘NewConnectionError(’<urllib3.connection.VerifiedHTTPSConnection object at 0x10b38ed50>: Failed to establish a new connection: [Errno 61] Connection refused’,)’: /login?client_secret=hidden&client_id=hidden

Did I miss some configuration step?

Fixed it by appending /api/3.0 to base_url e.g. base_url =

Sorry for any confusion I may have created.


Excellent! Sorry for not replying yesterday. Are you fully up and running with API 3.0?

So excited to start working with the API.

I followed these instructions and got the python client to work. My question is that no matter which format i pass to run_look, I always get the same format back.

I had

myresult = looks.run_look(1012,'json')
print myresult 

and i get

[{u'': u'71'}, {u'': u'88'}, {u'': u'89'}, {u'': u'92'}, {u'': u'97'}, {u'': u'102'}, {u'': u'108'}, {u'': u'109'}, {u'': u'114'}, {u'': u'119'}, {u'': u'121'}, {u'': u'126'}, {u'': u'133'}, {u'': u'151'}, {u'': u'152'}, {u'': u'169'}]

and if i change the format to csv, or sql or whatever, I still get that same result.

It looks like json, but when I try to call json.loads(myresult) it errors causing me to believe its not json.

Any thoughts?



I’ll need to look into this a bit more; however, when I open up my Swagger-generated source code, I see the following (line 245 in .../python/build/lib/lookerpython/apis/

resource_path = '/looks/{look_id}/run/{format}'.replace('{format}', 'json')

That replace may suggest that Swagger is going to override any format argument with “json,” because that’s all it’s prepared to handle.

I need re-generate using a more recent swagger.json to fully assess what’s going on. But I did encounter this exact issue when I first generated a Java client as well. Also, the fact that none of the package’s imports referene csv seems suspicious.

Stay tuned. I’ll update as soon as I know something.