{"size": 18430, "ext": "scrbl", "max_stars_repo_path": "manual.scrbl", "max_stars_repo_name": "greghendershott/gapi", "max_stars_repo_stars_event_min_datetime": "2015-04-08T21:13:10.000Z", "max_stars_repo_stars_event_max_datetime": "2019-06-05T08:34:38.000Z", "max_issues_repo_path": "manual.scrbl", "max_issues_repo_name": "greghendershott/gapi", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "manual.scrbl", "max_forks_repo_name": "greghendershott/gapi", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": 4, "max_issues_count": null, "max_forks_count": null, "avg_line_length": 40.4166666667, "max_line_length": 194, "alphanum_fraction": 0.7243081932}
#lang scribble/manual

@(require planet/scribble
          (for-label racket)
          (for-label json)
          (for-label (this-package-in main))
          (for-label (this-package-in dynamic))
          (for-label (this-package-in macro))
          )

@title{GAPI: Google API Discovery Service}

@table-of-contents{}

@; ----------------------------------------------------------------------------

@section{Introduction}

The Google API Discovery service is a web service that tells you about
web services.  Each web service is described using a JSON format
"discovery document", which describes such things as the resources,
methods, and parameters for the web service.  It is possible to use
this document programatically to create Racket functions that will
make HTTP requests to the web service, as well as to make
documentation for the service.

This library provides two approaches to using the discovery service
with Racket:

1. "Require" the discovery document like a source file. The wrapper
functions are created at compile time. The discovery documents are not
used at runtime and need not be shipped with your application;
essentially they are source code just like your @tt{.rkt} files.

2. Dynamically load and parse the discovery document (from a local
file or from the Discovery web service) at runtime.

Unless you need runtime dynamism, the first approach is easier, more
efficient, and simpler for distributing your application.

The functions created by either approach are identical in terms of the
arguments they accept and the value they return.  As a result you
should be able to change approaches without modifying much of your
code.


@section{Quick Start}

Let's say you simply want to use one of the Google web services.

1. If you don't already have one, get an API key from Google's
@hyperlink["https://code.google.com/apis/console/" "API Console"].

2. Put your Google API key in a @tt{.google-api-key} file in your home
directory (On Unix and OS X: @tt{~/.google-api-key}.)

3. Find the name of the discovery document corresponding to the
service you want to use; see @Secref["service-docs"].  For example,
you want to use the goo.gl URL shortener service, and find that its
name is @tt{urlshortener.v1.js}.

4. Use @racket[require-gapi-doc] to define Racket functions. For
instance:

@codeblock{
#lang racket
(require (planet gh/gapi/macro))
(require-gapi-doc urlshortener.v1.js)
}

5. Use the resulting functions to make requests to the service.

For example:

@codeblock{
;; Use goo.gl to make a short URI
(define js (urlshortener-url-insert #:longUrl "http://www.racket-lang.org/"))
(dict-ref js 'id)
}

In this example, the @racket[urlshortener-url-insert] procedure was
defined when you did @racket[(require-gapi-doc urlshortener.v1.js)]
in step 4.

You can find documentation of the functions defined for each service
using the links provided in @Secref["service-docs"].

In general the web services will return JSON which is parsed and
returned to you as a @racket[jsexpr?] via the Racket @racket[json]
collection.


@; ----------------------------------------------------------------------------

@section{Macro}

The simplest approach creates wrapper functions for the web service at
compile time. This reduces startup time for your
application. Furthermore, it means that you don't need to ship the
service documents---they are "source code" just like your @tt{.rkt}
files.

@defmodule/this-package[macro]

@defform[(require-gapi-doc discovery-document-name)]{

Defines functions respresenting the web service defined by the JSON
file named @racket[discovery-document-name].

@racket[discovery-document-name] may be either a fully qualified
pathname, or a literal that is the name of one of the
@Secref["service-docs"].

Each defined function makes an HTTP request to the web service. The
function takes keyword arguments. These values are supplied in the
HTTP request to the service.

The web service responds with JSON, which is returned by the wrapper
function as a @racket[jsexpr?]. This library doesn't try to marshal
the response into structs. Instead you will need to understand its
format and retrieve the information, for example @racket[(hash-ref js
'items)] if the response contains a list of items.

Every Google services takes an optional @tt{key} query parameter for a
Google API key. The wrapper functions provide this as a @racket[#:key]
argument. As a convenience, the @racket[#:key] argument defaults to
the @racket[api-key] Racket parameter. Put your Google API key in a
file named @tt{.google-api-key} in your home directory---in other
words, @tt{~/.google-api-key}.

As another convenience, see the @racket[paged] form which simplifies
making repeated calls to a service that returns results in small
"pages" (batches of results).

Example:

@codeblock{
#lang racket

(require (planet gh/gapi/macro))
(require-gapi-doc urlshortener.v1.js)

(define orig-url "http://www.racket-lang.org/")
(define js-insert (urlshortener-url-insert #:longUrl orig-url))
(define short-url (dict-ref js-insert 'id))
(define js-get (urlshortener-url-get #:shortUrl short-url))
(define long-url (dict-ref js-get 'longUrl))
(printf "~s was shortened to ~s, which expanded back to ~s: ~a"
        orig-url short-url long-url
        (if (equal? orig-url long-url) "Yay!" "Boo!"))
}

}

@; ----------------------------------------------------------------------------

@section{Dynamic}

@defmodule/this-package[dynamic]

Another way to use the API discovery service is to query it at
runtime. This may be desirable if you want to be able to discover
newly-added services.


@defproc[(service? [v any/c]) boolean?]{

Returns @racket[#t] if @racket[v] is a service, @racket[#f] otherwise.

A @racket[service?] is a @racket[jsexpr?] to which procedures have
been added.

}


@defproc[(discovery-document->service [discovery-document jsexpr?]) service?]{

Create a @racket[service?] object representing the web service defined
by the JSON provided as a @racket[jsexpr?].

}


@defproc[(local-discovery-document->service
[filename (or/c symbol? path-string?)]
) service?]{

Create a @racket[service?] object representing the web service defined
by the JSON file @racket[filename].

If @racket[filename] is a @racket[symbol?], then it should be one of
the @Secref["service-docs"].

}


@defproc[(online-discovery-document->service
[name string?]
[ver string?]
) service?]{

Create a @racket[service?] object representing the web service defined
by the name and version, which is fetched via HTTP from the Google API
Discovery service.

}


@defproc[(method-proc
[service service?]
[resource-name symbol?]
[method-name symbol?]
) procedure?]{

Given a @racket[service?], @racket[resource-name], and
@racket[method-name], get a procedure that makes HTTP requests to the
service.

The procedure returned by @racket[method-proc] is like that created by
@racket[require-gapi-doc]; see that for more information.

}

@; ----------------------------------------------------------------------------

@section{General}

@defmodule/this-package[main]

These are provided by both the @racket[gapi/dynamic] and
@racket[gapi/macro] modules.

@defparam[api-key key string?]{

Your Google API key.

Get an API key from Google's
@hyperlink["https://code.google.com/apis/console/" "API Console"].

Put your Google API key in a @tt{~/.google-api-key} file.


}


@defproc[(list-services
[#:name name (or/c string? 'N/A) 'N/A]
[#:label label (or/c string? 'N/A) 'N/A]
[#:only-preferred? only-preferred? boolean? #t]
) jsexpr?]{

Make a request to the Google API Discovery service to list available
services. Supplying @racket[#t] for @racket[only-preferred?] limits
the results to non-deprecated services or only the latest version of
services.

}


@defproc[(get-discovery-document
[name string?]
[ver string?]
) jsexpr?]{

Get the discovery document for the service @racket[name] and
@racket[ver]. Parse the JSON discovery document using
@racket[bytes->jsexpr] and return the resultng @racket[jsexpr?].

}


@defproc[(download-discovery-document
[name string?]
[ver string?]
[path path-string? (string-append name ".js")]
) any]{

Download the discovery document for the service @racket[name] and
@racket[ver] to the local file @racket[path].

}


@defproc[(load-discovery-document
[path path-string?]
) jsexpr?]{

Load the discovery document.

}

@defform[(paged (function arguments ...))]{

Make repeated calls to @racket[function] with @racket[arguments] if
necessary to obtain additional results. If the web service includes a
@tt{nextPageToken} value in the results---indicating that more results
are available---then @racket[function] is called again with
@racket[arguments] plus the additional argument
@racket[#:pageToken]. This repeats until the service no longer returns
a @tt{nextPageToken}.  In the returned @racket[jsexpr?], the total
results are appended into the value for the @racket['items] key.

Keep in mind that you may @italic{want} to make the calls individually
and process the results in small batches. You may want to do this if
the total results might be too large to fit in memory, or if you are
relaying the results to some other web service that would prefer to
take them in small batches, too.  However if you really want the
results accumuluated for you, use this form.

}

@; ----------------------------------------------------------------------------
@section[#:tag "service-docs"]{Available services}

The following service documents are shipped with this library. They
are located in the @tt{vendor} subdirectory of this library's location
in your PLaneT cache.

You may reference one with the @racket[require-gapi-doc] form by
supplying its name literally---for example, @racket[(require-gapi-doc
plus.v1.js)]. Notice that @racket[plus.v1.js] is neither a
@racket[string?] nor a @racket[symbol?].

You may reference one with the
@racket[local-discovery-document->service] procedure by supplying its
name as a @racket[symbol]---for example,
@racket[(local-discovery-document->service 'plus.v1.js)]. Notice that
@racket['plus.v1.js] is a @racket[symbol?] with a leading quote.

Each service listed below has a link to documentation which was
generated from its discovery document. In that documentation there is
also a link to Google's "normal" documentation, which you can read for
a fuller explanation of the service.

@itemize[
@item{@hyperlink["adexchangebuyer.v1.1.js.html" "adexchangebuyer.v1.1.js"] : Lets you manage your Ad Exchange Buyer account.}
@item{@hyperlink["adsense.v1.1.js.html" "adsense.v1.1.js"] : Gives AdSense publishers access to their inventory and the ability to generate reports}
@item{@hyperlink["adsensehost.v4.1.js.html" "adsensehost.v4.1.js"] : Gives AdSense Hosts access to report generation, ad code generation, and publisher management capabilities.}
@item{@hyperlink["analytics.v3.js.html" "analytics.v3.js"] : View and manage your Google Analytics data}
@item{@hyperlink["androidpublisher.v1.js.html" "androidpublisher.v1.js"] : Lets Android application developers access their Google Play accounts.}
@item{@hyperlink["audit.v1.js.html" "audit.v1.js"] : Lets you access user activities in your enterprise made through various applications.}
@item{@hyperlink["bigquery.v2.js.html" "bigquery.v2.js"] : A data platform for customers to create, manage, share and query data.}
@item{@hyperlink["blogger.v3.js.html" "blogger.v3.js"] : API for access to the data within Blogger.}
@item{@hyperlink["books.v1.js.html" "books.v1.js"] : Lets you search for books and manage your Google Books library.}
@item{@hyperlink["calendar.v3.js.html" "calendar.v3.js"] : Lets you manipulate events and other calendar data.}
@item{@hyperlink["civicinfo.us_v1.js.html" "civicinfo.us_v1.js"] : An API for accessing civic information.}
@item{@hyperlink["compute.v1beta12.js.html" "compute.v1beta12.js"] : API for the Google Compute Engine service.}
@item{@hyperlink["coordinate.v1.js.html" "coordinate.v1.js"] : Lets you view and manage jobs in a Coordinate team.}
@item{@hyperlink["customsearch.v1.js.html" "customsearch.v1.js"] : Lets you search over a website or collection of websites}
@item{@hyperlink["dfareporting.v1.1.js.html" "dfareporting.v1.1.js"] : Lets you create, run and download reports.}
@item{@hyperlink["discovery.v1.js.html" "discovery.v1.js"] : Lets you discover information about other Google APIs, such as what APIs are available, the resource and method details for each API}
@item{@hyperlink["drive.v2.js.html" "drive.v2.js"] : The API to interact with Drive.}
@item{@hyperlink["freebase.v1.js.html" "freebase.v1.js"] : Lets you access the Freebase repository of open data.}
@item{@hyperlink["fusiontables.v1.js.html" "fusiontables.v1.js"] : API for working with Fusion Tables data.}
@item{@hyperlink["gan.v1beta1.js.html" "gan.v1beta1.js"] : Lets you have programmatic access to your Google Affiliate Network data.}
@item{@hyperlink["groupssettings.v1.js.html" "groupssettings.v1.js"] : Lets you manage permission levels and related settings of a group.}
@item{@hyperlink["latitude.v1.js.html" "latitude.v1.js"] : Lets you read and update your current location and work with your location history}
@item{@hyperlink["licensing.v1.js.html" "licensing.v1.js"] : Licensing API to view and manage license for your domain.}
@item{@hyperlink["moderator.v1.js.html" "moderator.v1.js"] : Moderator API}
@item{@hyperlink["oauth2.v2.js.html" "oauth2.v2.js"] : Lets you access OAuth2 protocol related APIs.}
@item{@hyperlink["orkut.v2.js.html" "orkut.v2.js"] : Lets you manage activities, comments and badges in Orkut. More stuff coming in time.}
@item{@hyperlink["pagespeedonline.v1.js.html" "pagespeedonline.v1.js"] : Lets you analyze the performance of a web page and get tailored suggestions to make that page faster.}
@item{@hyperlink["plus.v1.js.html" "plus.v1.js"] : The Google+ API enables developers to build on top of the Google+ platform.}
@item{@hyperlink["prediction.v1.5.js.html" "prediction.v1.5.js"] : Lets you access a cloud hosted machine learning service that makes it easy to build smart apps}
@item{@hyperlink["reseller.v1.js.html" "reseller.v1.js"] : Lets you create and manage your customers and their subscriptions.}
@item{@hyperlink["shopping.v1.js.html" "shopping.v1.js"] : Lets you search over product data.}
@item{@hyperlink["siteVerification.v1.js.html" "siteVerification.v1.js"] : Lets you programatically verify ownership of websites or domains with Google.}
@item{@hyperlink["storage.v1beta1.js.html" "storage.v1beta1.js"] : Lets you store and retrieve potentially-large, immutable data objects.}
@item{@hyperlink["taskqueue.v1beta2.js.html" "taskqueue.v1beta2.js"] : Lets you access a Google App Engine Pull Task Queue over REST.}
@item{@hyperlink["tasks.v1.js.html" "tasks.v1.js"] : Lets you manage your tasks and task lists.}
@item{@hyperlink["translate.v2.js.html" "translate.v2.js"] : Lets you translate text from one language to another}
@item{@hyperlink["urlshortener.v1.js.html" "urlshortener.v1.js"] : Lets you create, inspect, and manage goo.gl short URLs}
@item{@hyperlink["webfonts.v1.js.html" "webfonts.v1.js"] : The Google Web Fonts Developer API.}
@item{@hyperlink["youtube.v3.js.html" "youtube.v3.js"] : Programmatic access to YouTube features.}
@item{@hyperlink["youtubeAnalytics.v1.js.html" "youtubeAnalytics.v1.js"] : Retrieve your YouTube Analytics reports.}
]

@; ----------------------------------------------------------------------------

@section{Examples}

See the @tt{examples} subdirectory or
@hyperlink["https://github.com/greghendershott/gapi/tree/master/examples"
"GitHub"] for examples.

For this documentation, here is one example of an example (ha ha
ha). This example uses OAuth2 to access Google+ user posts.

@codeblock{
#lang racket

(require (planet ryanc/webapi))   ;for OAuth
(require (planet gh/gapi/macro))  ;for Google web services...
(require-gapi-doc plus.v1.js)     ;..specifically Google+

;; For this example to work, you must go to the Google API Console and
;; create an application, such as "Racket GAPI Example". Put the
;; resulting client ID and client secret here:
(define my-client-id "put your client ID here")
(define my-client-secret "put your client secret here")

(define client (oauth2-client #:id my-client-id
                              #:secret my-client-secret))

(define scopes (list "https://www.googleapis.com/auth/plus.me"))

;; This will open a browser window so you can authorize.
(define auth (oauth2/request-auth-code/browser google-auth-server	 
                                               client	 
                                               scopes))

;; Use the access token. We can supply a userId of "me".
(define access-token (send auth get-access-token #:re-acquire? #t))
(plus-activities-list #:userId "me"
                      #:collection "public"
                      #:oauth_token access-token)
}


@; ----------------------------------------------------------------------------
@section{License}

Copyright (c) 2012, Greg Hendershott.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

@itemize[

@item{ Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer. }

@item{ Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. }

] @;itemize

@tt{
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}

@; ----------------------------------------------------------------------------
