Writing the API: A Simple GET

Cloud Endpoints Frameworks v1 has been deprecated and will be shut down on August 2, 2018. We recommend that you use the latest version of this feature, which is renamed to Cloud Endpoints Frameworks for App Engine. This new version supports App Engine standard environment, provides lower latency, and has better integration with App Engine. For more details, see Migrating to 2.0.

In this part of the tutorial, you'll create a backend API with methods serving two different HTTP GET requests:

  • A HTTP GET request that returns a list of hardcoded greeting objects.
  • A HTTP GET request that includes the integer 0 or 1 in the path to specify a particular greeting.

You can checkout the code for this sample using git, or you can browse the sample on github

git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
cd python-docs-samples/appengine/standard/endpoints

Coding a backend with a simple HTTP GET method

The app.yaml configures the endpoints API URL handler:

runtime: python27
threadsafe: true
api_version: 1

# The endpoints handler must be mapped to /_ah/spi.
# Apps send requests to /_ah/api, but the endpoints service handles mapping
# those requests to /_ah/spi.
- url: /_ah/spi/.*
  script: main.api

- name: pycrypto
  version: 2.6
- name: endpoints
  version: 1.0

The main.py file imports the endpoints and protorpc libraries need to create a backend API:

import endpoints
from protorpc import message_types
from protorpc import messages
from protorpc import remote

Then, the message classes are defined. These messages are used to define the requests and responses for the API:

class Greeting(messages.Message):
    """Greeting that stores a message."""
    message = messages.StringField(1)

class GreetingCollection(messages.Message):
    """Collection of Greetings."""
    items = messages.MessageField(Greeting, 1, repeated=True)

STORED_GREETINGS = GreetingCollection(items=[
    Greeting(message='hello world!'),
    Greeting(message='goodbye world!'),

Note that the sample also defines a hard-coded list of messages. This is so that the sample doesn't have to use a database and keeps things simple.

Next, the sample defines the API service. The API service defines and implements the methods that are available for the API. This API has two methods:

  • The list_greetings method returns the hardcoded list of greetings.
  • The get_greeting method returns a single greeting from the list of greetings given an index.
@endpoints.api(name='greeting', version='v1')
class GreetingApi(remote.Service):

        # This method does not take a request message.
        # This method returns a GreetingCollection message.
    def list_greetings(self, unused_request):
        return STORED_GREETINGS

    # ResourceContainers are used to encapsuate a request body and url
    # parameters. This one is used to represent the Greeting ID for the
    # greeting_get method.
    GET_RESOURCE = endpoints.ResourceContainer(
        # The request body should be empty.
        # Accept one url parameter: an integer named 'id'
        id=messages.IntegerField(1, variant=messages.Variant.INT32))

        # Use the ResourceContainer defined above to accept an empty body
        # but an ID in the query string.
        # This method returns a Greeting message.
        # The path defines the source of the URL parameter 'id'. If not
        # specified here, it would need to be in the query string.
    def get_greeting(self, request):
            # request.id is used to access the URL parameter.
            return STORED_GREETINGS.items[request.id]
        except (IndexError, TypeError):
            raise endpoints.NotFoundException(
                'Greeting {} not found'.format(request.id))

Finally, the sample defines the API server which is responsible for routing requests to an individual service.

api = endpoints.api_server([GreetingApi, AuthedGreetingApi])

Running and testing your backend API

To run and test the backend you just created:

  1. Start a new Chrome session as described in How do I use Explorer with a local HTTP API and specify 8080 as the localhost port (localhost:8080). Alternatively, you can use Firefox and temporary disable mixed content blocking.

  2. In the project directory, start the development server:

    dev_appserver.py .

    When the backend is running successfully, a message similar to this one is displayed:

    INFO     2013-10-07 19:41:16,687 admin_server.py:117] Starting admin server at: http://localhost:8000

    Something go wrong? See Using the Local Development Server for more information.

  3. In your browser, visit this URL:


    This opens up the API Explorer for your backend. Notice the list of APIs displayed with Greeting API in that list.

  4. Click greeting to display the available methods. Click greeting.greetings.get to display the Explorer form for it:


  5. The simple backend has two "canned" messages in an array. Get the first message by entering a value of 0 in the Id text box, then click Authorize and execute.

  6. Notice the display of the request and response. In the Response, you'll see the OK result and the returned message, hello world!.

  7. Enter a value of 1 in the Id text box, then click Authorize and execute; this time the message is goodbye world!.

Code summary

The Greeting message class is defined for the requests coming into the greetings.list and greetings.get methods and the responses returned by them. A message class performs a mapping function so the incoming data can be extracted and supplied to the service method properly, or supplied properly to the outgoing response. The greetings.list method returns several Greetings, so we use a GreetingCollection message class that supports this.

The name and version of the API is specified in the class decorator @endpoints.api(name='greeting', version='v1'). A complete list of decorator arguments is provided in the topic Defining the API.

Notice that a class used for the API must be a ProtoRPC service class, as shown above in the line class GreetingApi(remote.Service). (An Endpoints API is an RPC service that provides remote methods accessible to external clients.)

Notice the difference in the API method decorators in the list and get methods. The list method supports GET requests with no arguments, and therefore specifies the predefined message_types.VoidMessage for the request message. The get method supports a request containing an argument in the URL, so it must specify a ResourceContainer.

In both method decorators, we supply the path to specify a location at which the method serves requests. The value specified is appended to the API path, for example, if the value foo is specified, the path is https://your-app-id.appspot.com/_ah/api/greeting/v1/foo. For greetings.get, the path is greetings/{id} where {id} is required or else your API method won't receive the incoming request argument.

Finally, code is provided to create the API server. You could optionally do this in a separate module if you wish. For more information, see Creating an API Server.

What's next

Next, you will add a simple HTTP POST.

Continue to Writing the API: a Simple POST.

Was this page helpful? Let us know how we did:

Send feedback about...

Cloud Endpoints Frameworks for App Engine