21 Custom API Design

In Oracle Mobile Cloud Service (MCS), you can create custom REST APIs that can be used by your mobile apps. If you’re a mobile app developer, use the API Designer to sketch out and test the endpoints that you define and then have a service developer fill out the details of the API (add resource types or traits, provide a schema, and set the access to the API and its endpoints), and implement it in JavaScript. If you’re a service developer, use the API Designer to explicitly configure a complete API that you can test with mock data. Alternatively, you can generate custom APIs from a REST or Fusion Applications connectors without writing any code.

Unlike the MCS platform APIs, which provide a core set of known services, custom APIs let you use Node.js to code any service your mobile app needs, published through a REST interface. You can relay data by using an MCS connector to a backend service, which transforms complex data into mobile-friendly payloads. By using custom APIs to build a catalog of reusable services, you can save lots of time that might otherwise be spent periodically re-creating and maintaining implementation details in your mobile apps.

If you want to create an API quickly by providing sample data and letting MCS define a set of endpoints for you, use the Express API Designer.

API Design Process

The API Designer guides you through the process of creating a custom API.

You can quickly create a draft version of the API in just a few steps:

  1. Add the basics (name of the API, the message media type, and a brief description).

  2. Define an endpoint by setting a resource and at least one method for it.

  3. Set access security.

  4. Test your endpoint after you've defined at least one resource.

You can create mock data to quickly test and validate an endpoint even when you haven’t completely finished configuring your API. When you define your message body, you can provide placeholder values to verify that the correct data is being sent or returned. See Testing API Endpoints Using Mock Data.

Completing Your Custom API

To fully complete your API, use the API Designer to help you add the essential components for a robust API:

  • Provide the API metadata (that is, the basic attributes of the API, which are the API display name, API name, and short description) or, if you already have a RAML document that contains the configuration of your API, then you can upload it to the API Designer. All the information (metadata, resources, methods, and the schema for the message body) is extracted from the RAML document and loaded into the API Designer, letting you quickly proceed to testing your endpoints or editing your API configuration. To provide a valid RAML file, see RAML.

  • Add one or more root and nested resources.

  • Add methods to act on the resources.

  • Create a schema to describe the body of data.

  • Test your endpoints during design time with sample data and make any changes as needed.

  • Allow anonymous access to your API or specify which roles can access it.

  • Add documentation for your custom API

Later on, as you create more APIs, you might find that you are repeatedly defining the same methods, using the same parameters, etc. You can reduce the redundancy by creating resource types and traits. If your API is still in the draft state, then you can go back into your configuration and add the resource types and traits that you’ve defined.

The API Designer

The API Designer helps you configure a custom API with task-specific tabs that you use to name your API, define its endpoints, set security, add API documentation, add a schema, define resource types and traits, and test the API.

When you double-click an existing API, it automatically opens in the API Designer. Only APIs in draft state can be edited. If you open a published API, then it’s displayed as read-only information. To make changes to a published API, you need to create a new version of it (see Creating a New Version of an API).

While you’re configuring the API, you can switch between the Design view and the Source view. In the Design view (the default view), you enter values in fields. In the Source view, you manually define the API’s properties in a source code editor. Click Enter RAML Source Editor Mode open the RAML Source Editor icon. to toggle between the Design and Source views.

If you already have a RAML document, then you can import it and edit it in the API Designer. Click Upload a RAML Document or drag and drop your RAML document in the New API dialog to download your API definition.

Note:

If you came to the API Designer by clicking the APIs navigation link from a mobile backend, the feature to upload a RAML document is not available.

MCS APIs are based on the RESTful API Modeling Language (RAML) standard. Once you’ve begun to configure your API, MCS generates a RAML document of the configuration. See RAML to learn more about it.

If you want to work on the RAML document outside of MCS, you can export it by clicking Export RAML document export a RAML document icon at the top of the page.

Generating Custom APIs for Connectors

Oracle Mobile Cloud Service (MCS) can generate custom code from connectors to connect to external services. As a service developer, you can select a Fusion Applications connector or a REST connector that has been created with a valid descriptor, generate the custom API, and use the generated API to make it easier to call these services from the implementations of your custom APIs, or directly from a mobile app.

A connector is a means of enabling a mobile backend to communicate with an external service such as enterprise system or third-party APIs, which in turn, allows a mobile app to interact with the functions of that service. A connector API is a configuration for communicating with a specific external service to send and receive data.

As a service developer, you can generate a custom API that exposes the methods of a connector API and provides a default implementation, without writing code.

The custom API is generated with an endpoint for each resource in the connector API, and it is opened in the API Designer for you to continue to specify details of the API, such as roles. The default implementation, passes through all the requests coming from the generated custom API to the target connector API, is also generated and assigned to the generated API. As soon as you have assigned roles to the API if they are required for security on the connector you can use the implementation to test the API. You can download and modify the implementation and then upload it.

Creating a Generated Custom API for a Connector

Being able to create a custom API for a connector means that it is much easier to create a prototype which you use to test a connector. As you find things you want to change, you can quickly make a change to the connector, and generate a new custom API and implementation. Once you are satisfied you can generate a final version of the custom API and implementation.

  • First, you develop a REST connector or Fusion Applications connector that is defined using a descriptor.

  • Generate the custom API from the connector. It opens in the API Designer, where you can define one or more roles or specify the authentication required by the API.

  • You can immediately call the generated API from the mobile device. The default implementation passes through all the requests coming from the generated API to the target connector API.

  • You will probably want to download the implementation and modify it to shape the data returned.

  • You may want to revisit the connector and make changes to the connector resources or descriptor. If you do you must generate a new custom API and implementation. If you make changes to the generated custom API, these changes are not reflected in the connector. You should make the appropriate changes in the connector and then generate the custom API and implementation again.

Limitations of Generated Custom APIs for Connectors

You can only generate a custom API for a REST or Fusion Applications connector which is defined using a descriptor. You cannot generate a custom API for another type of connector, or where the REST or Fusion Applications connector does not have a descriptor.

If you want to send multipart form data or use the http options object, you might need to replace the callConnector method in the implementation with your own code. See Calling Connector APIs from Custom Code.

How Do I Generate a Custom API from a Connector

Before you can generate your custom API, you must have created the connector that the API will be configured for. If the connector isn’t valid you’ll see a popup explaining that you can only generate custom connector API code for:
  • REST connectors that use a descriptor URL

  • Fusion Applications connectors

Note:

Make sure that you have the descriptor defined for the connector, and that you have selected the resources and methods you want to generate code for. The connector should be as complete as possible
  1. Make sure that you’re in the environment for which you want to generate the custom API.

  2. Click open the side menu icon and select Applications > APIs from the side menu.

    The Connectors page appears. Select the connector API you want to generate custom code for. You can filter the list to see only the connector APIs that you're interested in or click Sort to reorder the list.

  3. Click More and from the drop-down list, select Generate Custom API.

    The Generate Custom API dialog appears.
  4. Provide the following information for the generated custom API:

    1. Title: Enter a descriptive name (an API with an easy-to-read name that clearly identifies the API makes it much easier to locate in the list of custom APIs).

      For example, myCustomAPI.

      Note:

      The names you give to a custom API (the value you enter in the API name field) must be unique among custom APIs.
    2. Version: Enter a version number.

      If you enter a version number that already exists, you'll get a message letting you know that number is already in use.

    3. Name: The title you entered is automatically entered here as the name. You can change it if you want. This name is used a unique name for your custom API.

      By default, this name is appended to the relative base URI as the resource name for the custom API. You can see the base URI below the Name field.

      Note:

      The custom API name must consist only of alphanumeric characters. It can’t include special characters, wildcards, slashes /, or braces {}.

      If you edit the name for the API here, the base URI is automatically updated.

      Other than a new version of this custom connector API, no other custom connector API can have the same resource name.

    4. Description: You can accept the default description, or provide a brief description, including the purpose of this API.

    After you've filled in all the required fields, click Generate.

    The draft API is generated and displayed in the General page of the API Designer (see The API Designer) where you can continue to edit it.

You can find the new custom connector API listed under Applications > APIs.

Completing the Custom API

The generated API opens in the API Designer.

  • An endpoint exists for all the resources selected in the connector, along with an implementation that you can use to test the API.

  • By default, security is set that login is required and security is enterprise level so you need to add the roles that can access the API. See Security in Custom APIs

As soon as you assign appropriate roles, you can test the custom API.

Working with the Implementation

The default generated implementation passed through all requests. You can edit the implementation to shape the data returned, which is useful if there is a lot of data.

  1. Make sure that you’re in the environment where you can download the implementation.

  2. Click open the side menu icon and select Applications > APIs from the side menu.

    The APIs page appears. Select the custom API that you have generated. You can filter the list to see only the custom APIs that you're interested in or click Sort to reorder the list.

  3. Click the Implementations navigation link, select the implementation which will have the same name as the custom API, and click Download.

  4. The download is a zip file with the default name <custom-api><version>.zip. Expand it to a suitable location. The implementation files are:

    • callConnector.js, passes the client’s request to the connector, and sends back the connector’s response.

    • <custom_api>.js , provides the main body of the scaffolding of the custom API implementation. You can uncomment lines in this to shape the data returned from the connector.

    • <custom_api>.raml, the RAML definition of the custom API.

    • package.json, the package descriptor file.

    • ReadMe.md, has a description of the implementation files.

    • samples.txt, code samples.

    • swagger.json, the Swagger definition of the custom API.

    • toolsConfig.json, used by the command-line development tools.

  5. In an appropriate editor, open <custom_api>.js, which is the only file in the generated implementation which you should edit.

    To shape the response from the connector, uncomment the relevant lines and if necessary change the type and limit. See the service.use examples in the sample of <custom_api>.js below.

    service.use(bodyParser.raw({type: 'application/octet-stream', limit: '100mb'}));

    and

    service.use(bodyParser.text({type: 'text/*', limit: '1mb'}));
    

    This is the first few lines of the <custom_api>.js generated implementation file.

    // no need to add body-parser as a dependency in package.json - it's provided by custom code container
    var bodyParser = require('body-parser');
    
    // passes client's request to the connector, sends back connector's response
    var callConnector = require('./callConnector.js');
    
    /**
     * Mobile Cloud custom code service entry point.
     * @param {external:ExpressApplicationObject}
     * service
     * @see {@link http://expressjs.com/en/4x/api.html}
     */
    module.exports = function(service) {
    
    // uncomment if using customizer to customize binary request with content-type 'application/octet-stream' - it will be parsed into a Buffer and assigned to req.body. Otherwise these requests streamed through (recommended approach if no customization is required).
    //service.use(bodyParser.raw({type: 'application/octet-stream', limit: '100mb'}));
    // uncomment if using customizer to customize text request with text content-type - it will be parsed into a string and assigned to req.body. Otherwise these requests streamed through (recommended approach if no customization is required).
    //service.use(bodyParser.text({type: 'text/*', limit: '1mb'}));
    
    // In the product UI, in Diagnostics -> Logs tab, ServerSetting button allows to set backend log level: set your mbe log level to FINE (FINER, FINEST) to see the generated custom code sdk calls.
    
    
    	service.post('/mobile/custom/sample_api/emps', function(req,res) {
    		// uncomment customizer to customize request and/or response
    		callConnector(req, res/*,customizer*/);
    	});
    
    	service.get('/mobile/custom/sample_api/emps', function(req,res) {
    		// uncomment customizer to customize request and/or response
    		callConnector(req, res/*,customizer*/);
    	});
    
    ...

There is a sample customizer in the same generated implementation file. You can edit it and pass it as a last parameter to callConnector to override the request sent to the connector and/or the connectors response. See the comments in the code for examples of what you can do.

// Edit this sample customizer and pass it as a last parameter to callConnector to override request sent to connector and/or connector's response.
// Without customizer callConnector streams request to connector, then connector's response is streamed back to client - recommended approach in case no customization is required.
var customizer = {
    // allows to customize request sent to connector. If omitted then the request streamed to the connector - recommended approach in case no request customization is required.
    request: {
        // used - with post and put only - to customize request body
        // If not specified then request body is streamed directly to the connector - no need to define this function unless you need to override the payload.
        body: function(req) {
            console.log('customizer.request.body: req.body = ', req.body);
            var body = req.body;
            // OVERRIDE request body here - substitute this sample code:
            if (typeof body == 'string'){
                // to enable string parsing uncomment  service.use(bodyParser.text... - otherwise req.body would never be a string
                body += ' customized request';
            } else if (typeof body == 'object'){
                if (Buffer.isBuffer(body)){
                    // to enable binary parsing uncomment  service.use(bodyParser.raw... - otherwise req.body would never be a Buffer
                    body = Buffer.concat([Buffer.alloc(8, '00000000'), body]);
                } else {
                    // json parsing is enabled by default
                    body['customized-request'] = true;
                }
            }
            console.log('customizer.request.body ->', body);
            return body;
        }/*,
        // advanced: uncomment to add options to connector request, see https://github.com/request/request#requestoptions-callback
        options: function(req) {
            var options = {headers: {myHeader: 'myHeaderValue'}};
            console.log('customizer.request.options ->', options);
            return options;
        }*/
    },

Spec Out a Custom API

As a mobile developer, you might want to quickly spec out an API for your backend then configure it later, or hand it to someone like the service developer to complete. You can construct a functioning API with just a few steps: name your API, define an endpoint, and test the endpoint. These next steps use a simplified FixItFast example. It doesn’t show you how to add method parameters, or schemas, or resource types and traits.

  1. Make sure that you’re in the environment containing the mobile backend for which you want to create a custom API.
  2. Click open the side menu icon and select Applications > Mobile Backends from the side menu.
  3. Select the mobile backend that you want to associate the API with from the list of backends and click Open.
  4. Click the APIs navigation link.
  5. Select New API > API.
    The New API dialog opens. Here’s where you enter the basic information for your API:
    1. Enter a name in the API Display Name field that is easy to read and describes your API. For example, FixItFast Incident Reports. This name appears in the API Catalog, which other developers can see.
      The name you give to a custom API (the values you enter in the API Display Name and the API Name fields) must be unique. No two custom APIs can have the same name.
    2. Enter a name in the API Name field for the internal name of the API. It’s part of the metadata of the API, that is, it appears in the custom API URI. It won’t appear in the API Catalog, so you can use a more concise form of the display name if you choose. For example, incidentreports.
    3. Add a brief description that tells others what the API does.
  6. Click Create.
    The General page of the API Designer is displayed. If you want to change the name of your API or its description, then you can do it here.
  7. Select the default media type, that is, the content type of the message body. REST APIs commonly use the application/json or the application/xml media type.
    That’s all you need to do to set the basic information for your API. If you’d like, you can choose a different icon to associate with the API display name or just go with the default and select a different icon later.
  8. Click Endpoints in the navigation bar to define endpoints for the API.
    1. Click New Resource and enter the resource name and the display name of the resource (the field next to the resource name field). For instance, you could have contacts as the resource name and Customer contacts as the display name. Resources are listed by their display names on the left side of the API Test page. Enter a brief description of the resource so others can understand what the resource does.

      Tip: This image shows a “P” under the Methods link. When a method is defined for an endpoint, an icon for the method appears below the Methods link. The icons are a shortcut you can use later to quickly see what methods are defined for the resource and you can go directly to the method definition by clicking on an icon.

      If you want to add another top-level resource, then click New Resource again and enter names and descriptions.

    2. (Optional) If you want to add a nested resource (a child resource of contacts), click Add (+) next to the Resource name field. Enter a name, a display name, and a description of the nested resource. Click Add (+) again to add more nested resources if you need them.
      Endpoints are what really define an API. They are the resources and the methods that act on those resources.

      If you want to know more about resources, see API Resources.

  9. Click Methods next to the resource display name and define a method for the resource.
    For each method, you need to define a request and a response. You can add parameters to filter the information for the request and response message bodies if you need them.
    1. Click Add Method, select an operation and, optionally, add a description of the method in the Description field.
      For example, you could select a POST method to create a customer and add “Creates a customer” as the description. Notice that a POST icon appears next to Add Method. All methods defined for a resource have icons displayed at the top of the page. When you want to view or edit a specific method, just click the icon for it.
    2. Click Add Media Type and select the format of the request message body, which is usually JSON or XML.
    3. Add a schema (a template of the message body) or an example of the message body using mock data. Click Example or click Schema to paste the message body.
      Here’s an example body you could use for the FixtItFast example:
      {
        "AddressLine":"1 Main Street',
        "City":"Anytown",
        "UserName":"user",
        "FirstName":"Jim",  
        "LastName":"Smith",
        "PostalCode":"12345"
      }
    4. Add a response body by clicking Add Response and selecting a response code. Don’t forget to add a description for the response body.
      Using the example, you would select 201 — Created for the POST method and enter the following description: Request fulfilled, new customer added.

      You can add parameters to filter information for the response body. You can also enter a response message body. If you’re using the FixItFast example, then a response body isn’t needed for the POST method.

    5. Save your method definitions by going to the top of the Methods page and clicking Save.
  10. Set security access for your API by clicking Endpoints to get back to the Endpoints page. From there, click the Security navigation link.
  11. Switch Login Required to OFF so you don’t have to provide mobile user credentials or access tokens for authentication and click Save.

    See Security in Custom APIs to learn more about securing access to the API. Now you’re ready to test your endpoint.

  12. Click Test to go to the API testing page.
    The endpoints defined for the API are listed on the left side of the page. Click an endpoint to load it. You can see each method’s request and response configurations for each resource.

    You can check the definition of each method and if you want to modify a parameter name or an example, enter the change in the box to the right of the field. If you click Use Example by a message body, then the current body is copied into the text editor and you can make any changes.

  13. In the Authentication section, select the mobile backend that this API is associated with and the mobile backend’s version number.

    Because you set Login Required to OFF, you don’t need to specify the authentication method or provide credentials.

    If you defined more than one endpoint, then set the default test credentials so you won’t have to fill out the Authentication field for each method. Click Default API Designer Test Credentials at the top of the page and select the associated mobile backend and its version number. When you click Save (save the current values icon), the values are applied to the Authentication fields of each method.

  14. Click Test Endpoint.

    You can view the request and response status and data of the test under the Response Status section. If you used the FixItFast example and your test was successful, then you should see a 201 status.

That’s all you need to do to spec out your custom API. As long as the API is in a draft state, you or a teammate can edit the API configuration as needed. For steps on how to fully configure a custom API, see Creating a Complete Custom API.

Creating a Complete Custom API

Previously, you learned how to spec out an API using the API Designer. You gave a name to the API, added at least one resource and method and tested your endpoint. At this point you have a draft version of the API but it isn’t quite complete. In this section, you’ll fill in more details (such as defining the method requests and response, adding a schema, and setting secure access) to make a more robust API. Just in case you’re starting from scratch though or want more details about setting the basics, the complete set of steps to creating a custom API are presented.

Click open the side menu icon and select Applications > APIs from the side menu. If an API has already been created (whether in a Draft or a Published state), you'll see a list of APIs. If no custom APIs exist, then you'll see a page with the New API button. Click the API you spec’d out already or click New API to get started.

Setting Up Your API

Let’s use the FixItFast example to create a custom API. In this example, you work for the FixItFast appliance repair company. You need to find a way to track the repair calls and responses. It would also be helpful to know which technicians are assigned to the repair jobs. You want to create an API that lists the customer service calls based on the customer who called to report the problem, the customer location, and the technician assigned to the job. You’ll create the following API with the following properties:

  • An API called FIFIncidentReports

  • A base URI: https://fif.mcs.cloud.oracle.com/mobile/custom/fif-incidentreport/

  • An application/json media type

  • An icon to associate with the API display name (a PNG file that we selected)

When you click Create, a Draft state of the API is created and added to the list of custom APIs.

First, set the basic characteristics for your API by going to the General page.

  1. Make sure that you’re in the environment containing the mobile backend for which you want to create a custom API.
  2. Click open the side menu icon and select Applications > APIs from the side menu.
  3. Select New API > API.

    You select API to craft custom APIs with the API Designer. Express API enables you to create API quickly without having to write any code as long as you have sample data to provide. See Creating An API to learn about the Express API Designer. If you’re developing mobile apps with the Mobile Application Accelerator (MAX), the Express API designer is the quickest way to develop APIs for use with MAX. See Creating APIs Fast with the Express API Designer for information about MAX.

  4. Enter a name for the API in the API Display Name field that will appear in the list of APIs (required).
    The display name can contain alphanumeric characters and special characters ( ! ? & @ ( ) _ - . ‘ “). The name can’t begin with a space and can’t exceed 100 characters.

    The name you give to a custom API (the values you enter in the API Display Name and the API Name fields) must be unique among custom APIs. For example, if a custom API exists with the API name My API, then you can’t create another custom API with the same name.

  5. Enter a name for the API in the API Name field that will appear in the API configuration (required).

    This name is appended to the relative base URI as the resource name for the API. The API name must begin with a letter (A - Z) and can contain numbers (0 - 9) and underscores (_). The name can’t exceed 100 characters. A validation error message is displayed if you enter a name that’s already in use.

    If you edit the name of the API here, then the change will be made automatically to the resource name in the local URI.

  6. Add a brief description of your API and click Create.

    You’re taken to the API Designer page where you can complete the basic information for your API:

    • Default media type for the payload (application/json is selected by default, click the drop-down list to select another type).

    • API Catalog Properties to make it easier for you and other developers to locate the API. Provide a brief description of your API and select an icon to associate with your API.

      If you want to use your own icon, then you can upload an icon (it must be in a PNG format) or if you’re creative, then you can download Photoshop QuickStart to use an icon template to create an icon. You should be familiar with using Photoshop to create an icon. Follow the icon guidelines for sizing and color information. For sizing information, see the Full Palette Icon section of the ALTA ICON STYLE chapter in the Oracle Alta Web Design Guide. You’ll need a 48x48 icon image within a 70x70 canvas. For color guidelines, see the Icon Palette section of the ALTA COLORS chapter of the same guide.

Now that you’ve provided the basic information, it’s time to define endpoints for your API.

Defining Endpoints

You create resources to define the endpoints of your API. A resource is the crux of an API. It has a type, some data associated with it, a relationship to other resources, and contains one or more methods that act on it. A resource can be nearly anything: an image, a text file, a collection of other resources, a logical transaction, a procedure, etc. See API Resources.

  1. Click the Endpoints navigation link to begin.
  2. Click New Resource and add some basic information.
    Each time you click New Resource, you create a top-level (root) resource. If you want to add a child (nested) resource, then click Add (+) next to the top-level resource. Click X to delete a resource.

    Note:

    See the icons under the Methods links? Each time you define a method for a resource, an icon for it appears under the Methods link. Use them as a shortcut to see what methods have already been define for a resource. Click on an icon to go directly to its definition on the Methods page.
  3. Provide the resource path, which is the URI (relative to the base URI). For example, if the base URI is /mobile/custom/fif-incidentreport, then you could add the resource, incidents, that is /mobile/custom/fif-incidentreport/incidents.
  4. Provide the display name, which is a name for the resource that makes it easy to identify in the API documentation.
    Resources are listed by their display names on the left side of the API Test page.
  5. Provide a brief description of the resource.

    After you enter a description, the URI is displayed below the description field.

  6. (Optional) Provide a RAML resource type, which is the resource type (resourcesType:). You don't need to specify a resource type. If you want to use a resource type but you don't have one defined, then click the Types link and define one. See Creating Resource Types.

When you create a method for a resource, a symbol for that method appears below the Methods link. You can immediately see what methods have defined for a resource if you need to examine a resource definition. Click on an icon to go directly to that method definition.

You can clear the clutter to locate a resource more quickly by switching to Compact Mode (it's to the right of New Resource). The compact display hides the resource description, resource type, and path.

Adding Methods to Your Resources

Methods are actions that can be performed on a resource. The Methods page shows you one method at a time. After at least two methods are defined, you can click on the icon for a method at the top of the page to see its details.

  1. Add some methods to the resource by clicking Methods.

    If the resource you're defining methods for has path parameters, then they are displayed above Add Method.

    1. (Optional) Click Required if you want the path parameters to be passed with each method.
      The parameter name is displayed.
    2. Provide a display name for the parameter and example code.
    3. From the drop-down list, select the valid value type for the parameter.
  2. Click Add Method and select the method that you want:
    Method Description

    GET

    Retrieve or read a resource

    POST

    Create a new resource

    PUT

    Update a resource

    DELETE

    Remove a resource

    HEAD

    Read the HTTPS metadata

    PATCH

    Perform a partial update of a resource

    OPTIONS

    Request information, such as the options or requirements of the resource

    After you've selected a method, it’s no longer listed in the method list because you use a method only once per resource (e.g., you can't define two DELETE methods for a single resource). An icon for each method that you define is displayed at the top of the page. Click on a method icon to go directly to its definition.

  3. (Optional) You can enter a brief description of the method in the Description field.
  4. (Optional) You can enter a display name for the method.
  5. (Optional) Provide any traits to apply to the method.

    If you don't have any resource traits defined, click <Endpoints to go back to the main Resources page and click the Traits link to define one. Traits let you define a collection of similar operations. See Creating Resource Traits.

After you’ve defined methods for the resource, you can define the requests and responses for those methods. See Defining a Request for the Method and Defining a Response for the Method.

Defining a Request for the Method

Now that you've selected a method, define the request you're making of the service that you want to connect to. For instance, if you selected a POST method, then now you can define what to create. You do this by adding parameters and a request body, which contains the description of the data to send to the service.

  1. Click Request to define a request.
  2. Click Add Parameter and select a parameter type: Query or Header. Select Required if the parameter is required for the method.
    1. Give the parameter a name and a display name.
    2. Select a valid value type: String, Number, Integer, Date, or Boolean.
    3. (Optional) Provide a description of the parameter and an example you can use when you test the validity of the endpoint. For example, you could have a resource, incidents, and add a query parameter, contact that takes a number value, and another parameter, gps that takes a string value:
      /incidents: 
        get: 
          description: | 
            Retrieves all incident reports for the filters below.     
          queryParameters: 
            contact:  
              displayName: Contact ID
              description: | 
                filter reports by contact 
              type: string 
              example: |
                lynn@gmail.com 
      
              required: false
            technician:
              displayName: Technician ID
              description: |
                filter reports by technician
              example: "joethetechnician"  
            gps:
              displayName: gps
              description: |
                location of contact or technician
              example: "39.355589 -120.652492"

      In this example, a GET method is defined with the query parameters, contact, technician, and location.

    4. (Optional) Click More Properties to add nested properties to the parameter. Click Repeat to add multiples of the current parameter.
    5. Click Add Parameter to add another top-level parameter for the method.
  3. Depending on the method you selected, click Add Media Type and define the method body. The body contains the data that you're sending to the server. For instance if you’re defining a POST method, you’ll need to define the item you’re creating, such as a new customer listing or service request. If you’re defining a GET method, you don’t need to send a method body so you don’t need to specify a media type.
    1. Select the media type for your method body, that is the format of the message that you're sending, such as text, images, or web forms.
      Depending on the type (for instance, you wouldn't enter a schema for an image type), you have the option of adding a schema or an example, or both.

      When defining a schema, add only the data necessary for the purpose of the resource. That is, don’t add unnecessary data that will only slow down the transmission and potentially increase the potential for errors.

    2. (Optional) Click Schema and enter a schema (in JSON format) in the editor pane. A schema is like a template for the body. It's what you use to define the contents of the message.

      For an example of a schema, see Providing a Schema.

    3. (Optional) Click Example and enter an example (in JSON format) in the editor pane, which is used by the mock implementation as a mock response for the method. Using mock data can help you verify the behavior of your methods. See Testing API Endpoints Using Mock Data. The example shows mock values for the data being sent in the message body as defined in the POST method of the incidents resource:
      body: 
        application/json: 
          example: | 
            { 
              "Title": "Leaking Water Heater",
              "Username": "joh1017",  
              "imageLink": "storage/collections/2e029813-d1a9-4957-a69a-fbd0d7431d77/objects/6cdaa3a8-097e-49f7-9bd2-88966c45668f?user=lynn1014", 
              "Notes": "my water heater is broken"
            }                               
      
  4. Click Add Media Type to add additional media types. If you decide that you don't want the method, then click X in the banner to delete it.

Defining a Response for the Method

Depending on the request, you may or may not need a response. A response describes the process for returning results from the service. You might want to define a response that verifies that the data you requested was returned or you might want a response that just acknowledges whether or not the request was received. Defining a response is similar to defining a request. The main difference is that you'll need to select a status code to let you know the result of the connection.

  1. Click Response to define one or more responses.
  2. Click Add Response and select the status code that you want returned.

    A status code of 200 is provided by default but if that isn’t the code you want, then select one from the drop-down list.

    • 2xx indicates a successful connection

    • 3xx indicates a redirection occurred

    • 4xx indicates a user error occurred

    • 5xx indicates a server error occurred

    To help whoever uses the API to understand the reason for a potential error in the API you’re configuring, use an HTTP status code to return code that best matches the error situation.

  3. Provide a description of what the code designates.
  4. Click Add Header, select a response Header or Query, provide the name of the header or query and a display name for the header, and the valid value type for the header.
  5. Click Add Media Type and select the format of the response. Depending on the media type you select, you can add parameters, schemas, or examples just as you did for the Request body.
    1. For text-based media type (e.g., application/json or text/xml), click Schema to enter a schema (in JSON format) for the body.
      As with the request body, add only pertinent data to the response body. Don’t include more data than you actually need for the operation.
    2. Click Example to add mock data (in JSON format) for your response body. Use mock data to verify the behavior of your methods before testing with real data. See Testing API Endpoints Using Mock Data.
    3. For form-based media type (e.g., multipart/form-data), click Add Parameter and select Required if the parameter is mandatory. Then provide a name and select a value type. Optionally, you can give your parameter a name.
    4. For image-based media type (e.g., image/png), you don’t have to do anything because there are no schemas or attributes to provide.
The following example shows that a response for the POST method of the incidents resource was created with a status code of 201 indicating a new resource was successfully created. The example also shows a return response format of application/json, a Location header that was added, and the message body containing mock data:
responses: 
  201: 
    description: | 
      The request has been fulfilled and resulted in a new resource 
      being created. The newly created resource can be referenced  
      by the URI(s)returned in the entity of the response, with the 
      most specific URI for the resource given by a Location header
      field.  

    headers:
      Location:
        displayName: Location
        description: |
          Identifies the location of the newly created resource.

        type: string
        example: |
          /20934

        required: true

    body: 
      application/json: 
        example: | 
          {
            "id": 20934,
            "title": "Lynn's Leaking Water Heater",
            "contact": {
               "name": "Lynn Adams",                 
               "street": "45 O'Connor Street",
               "city": "Ottawa", 
               "postalcode": "a1a1a1",
               "username": "johnbeta"
              },
           "status": "New",
           "driveTime": 30,
           "priority": "high",
           "notes": "My notes",
           "createdon": "2014-01-20 23:15:03 EDT",
           "imageLink": "storage/collections/2e029813-d1a9-4957-a69a-fbd0d74331d77/objects/6cdaa3a8-097e-49f7--9bd2-88966c45668f?user=lynn1014"
          }

When you've defined your response, you can decide to test your endpoints (see Testing API Endpoints Using Mock Data) or click <Endpoints in the navigation bar to return to the main Resources page. From there, you can proceed to another page in the API Designer to create a root, resource types or traits, or add API documentation.

If you decide you don't want the method, then click X in the banner to delete it.

Testing API Endpoints Using Mock Data

You can provide mock data in your request and response message bodies during the design phase of your API configuration. This lets you examine the context of each call without having to use real time data or interact with a real time service. For example, to test whether your code correctly handles an invalid ID, you can add an example in your request body with mock data containing an invalid ID. When you finish the test, you can replace the example with other code to test some other aspect of the method.

In the FixItFast example, the mock data in the response body lets you verify if the correct customer information is being returned. Here’s an example of mock data that the service developer could create for the response body of the POST operation of the contact resource in the FixItFast example:
{
 "id": 20934,
 "title": "Lynn's Leaking Water Heater",
       "contact": {
       "name": "Lynn Adams",
       "street": "45 O'Connor Street",
       "city": "Ottawa",
       "postalcode": "ala1a1"
       "username":"johneta"
       }
 "status": "new",
 "driveTime": 30,
 "priority": "high",
 "createdon": "2015-04-23 18:12:03 EDT"
}

When you create a custom API, a mock implementation is created automatically. The mock implementation lets you invoke the API from your mobile application before you’ve implemented the custom code. This lets you develop and test the mobile applications and the custom code simultaneously. If you’re satisfied with the configuration, you can add a real implementation.

Until you create your first implementation, the default implementation is the mock implementation. After you create a real implementation, it becomes the default implementation for the API.

Click the Implementations navigation link to upload an implementation or to see any existing implementations. You can change the default implementation on the Implementations page. After you upload an implementation, you see a list of existing implementations, which includes the mock implementation.

See Testing with Mock Data to learn more about testing an API with a mock implementation. See Implementing Custom APIs to create a real API implementation.

For details on testing fully-implemented custom APIs, see Testing Your Custom API.

Providing a Schema

You have the option of adding a JSON schema, which describes the structure of your data and is written in JSON. If you want to add a schema, go to the Schema page and click New Schema. After you've defined at least one schema, you can select one from the list.

To define a schema, provide:

  • The schema name

  • The schema definition (in JSON format) in the editor pane, which you can manually enter or copy and paste into the editor

For example, a schema called schema# is defined as follows:

schemas:
- reports: | 
      { 
        "$schema": "http://json-schema.org/draft-04/schema#", 
        "type": "array", 
        "description": "Incident Reports array", 
        "items": { 
          "type": "object", 
          "properties": { 
            "id":  { "description": "Unique id for the incident report", 
                     "type": "integer" }, 
            "title": { "description": "Title for the incident report", 
                       "type": "string" }, 
            "createdon": { "description": "Date and time of creation", 
                           "type": "string" },
            "contact": { "decription": "Contact information of customer filing the report", 
                           "type": "object",  
                           "properties": {
                             "id" : { "description": "Unique id for the customer", 
                                      "type" : "string" }, 
                             "name" : { "description": "First and last name of contact",
                                       "type" : "string" }, 
                             "street": { "description": "Street address of contact", 
                                       "type" :  "string"}, 
                             "city" : { "description": "City of contact", 
                                       "type" : "string"},
                             "postalcode" : { "description" : "Postalcdoe of contact",
                                               "type": "string" }
                             }
                  },
             "status" : { "description": "The current status of the incident",
                          "type" : "string" },
             "priority" : { "description": "The current priority of the incident", 
                          "type" : "string" }, 
             "driveTime" : {"description" : "Calculated field based on location",
                          "type" :  "integer"},
             "imageLink" : { "description" : "Link to image from Storage",
                           "type": "string" }
            },
          }
      }

Add more schemas to define by clicking New Schema. Click X to delete a schema. See Schemas for details about the structure of a JSON schema.

Note:

You can define multiple schemas for use with the given API. Schemas are specific to the API and aren’t shared across other APIs.

Security in Custom APIs

In MCS, an API is protected through its association with a mobile backend to allow only authorized users and devices to access the API and its endpoints.

For enterprise applications, you can use HTTP Basic Authentication, OAuth, or SSO OAuth Token credentials to control user authentication and authorization of access to resources:

  • With OAuth, when you create a mobile backend or register with an existing mobile backend, a set of OAuth consumer keys (that is, client credentials) consisting of a client ID and client secret are generated for you. The values of these keys are unique to the mobile backend (for information about authenticating with OAuth, see Authenticating with OAuth in Direct REST Calls). You authenticate yourself to the OAuth server by providing your client credentials and receive an access token that is passed in each API call via a header. Only a user with a valid token can access the API.

    Alternatively, you can provide a Single Sign-On OAuth token provided by your Remote Identity Provider if the Enable SSO option is selected for the mobile backend. For information on how to enable single sign-on for a mobile backend, see Authentication in MCS.

  • With HTTP Basic Authentication, when a mobile backend is created, a mobile backend ID and an anonymous access key are generated for it. You authenticate yourself to MCS by providing these items, which are passed in each API call via a header. You must provide this information to access the API. You can obtain the mobile backend ID and anonymous access key from the mobile backend landing page. Select the mobile backend associated with the API and expand the Keys section. To learn more about authenticating with HTTP Basic, see Authenticating with HTTP Basic in Direct REST Calls.

  • With Social Identity, when you register an app with a social identity provider (for example, Facebook), an access token is generated by the provider. You authenticate yourself to MCS by specifying the social identity provider and providing the access token.

    To find out how to get an access token, see Getting a Facebook User Access Token Manually.

To learn about authentication in MCS, see Enterprise Single Sign-On in MCS.

Setting Access to the API

You have the option of requiring developers to login and provide authentication credentials to access the API.

  • Set Login Required to OFF to allow access to the API from a mobile app as an anonymous user. Also, you won’t need to use authentication credentials on the API's Test page.

    This setting is particularly useful when you’re in the early phases of configuring your API and you just want to validate some endpoints or when the data being requested or received is from a service that doesn’t require security.

  • Set Login Required to ON to require authenticated access to the API:
    • Select Enterprise to set access for mobile users who login with their MCS username and password or who have configured Single Sign-On authentication providers.

      When you set Login Required to ON and select Enterprise, the API Access and Endpoint Access fields are exposed and you must select at least one role to access the API. This ensures that only those mobile users that have the selected role or roles can access the API endpoints. Click in the Roles field to select one or more roles.

      Optionally, you can further refine access to the API by selecting roles for specific endpoints. Only mobile users having the role selected for a specific endpoint can access it. For example, you can allow only users with a Mobile Develop role to access the DELETE method. Click in the field for each endpoint and select one or more roles.

    • Select Social Identity to set access for mobile users who want to use their social media accounts for authentication.

      If you choose this setting, you can save your API configuration and move on to the Test page. In addition to specifying the mobile backend and its version, you’ll be asked to select the social authentication provider and provide the access token generated for you by the selected provider.

Note:

You can obtain information about the current mobile and social users by including the ums.getUserExtended() method in the custom code for the API. See Accessing the Mobile Users API from Custom Code.

Testing Your Custom API

To validate your API endpoints, the Test page lets you test with sample response data. You’ll see a list of all the resources that you’ve defined on the left side of the page. Use the Filter endpoints field to display only the resources that you want to test. You test only one endpoint at a time.

Note:

A few things before you start testing your API:
  • If Login Required is turned ON and Enterprise is selected, you must have a role assigned that allows access to the API.

  • If Login Required is turned ON and Enterprise or Social Identity is selected, you must provide values for all fields in the Authentication section of each method to test it.

  • If Login Required is turned OFF, providing authentication credentials is optional.

  • Save your configuration before you test. If you haven’t, then you can check the Always save before testing option in the Save Before Testing confirmation dialog that appears when you click Test. That way, any changes that you make to the API configuration are automatically saved.

  1. If you are in the design phase and just want to see if your endpoints are valid, or if you want to test multiple endpoints during the session, then set the default API test credentials.
    1. Click Default API Designer Test Credentials at the top of the page.
    2. Select a mobile backend to associate the API with and the version of the mobile backend.
    3. Select one the authentication method to use for testing:. HTTP Basic, OAuth Consumer, Social, or Single-Sign On.
    4. If Enterprise is selected on the Security page, mobile users must enter their mobile user credentials (username and password).

      Credentials for social identity or for single-sign on are not required.

    5. Click Save (save the current values icon).

      The mobile user credentials that you enter will be used as the default credentials for all test calls made within Mobile Cloud Service.

    If you need to test only a few methods, skip Step 1 and fill out the fields in the Authentication section for each method (see Step 5).
  2. Select the method that you want to test from the list of endpoints on the left side of the test page.
    When you select an endpoint, the method banner for it is displayed with the base URI is displayed below the operation name. If you provided an alternate name for the operation, then that name appears, otherwise the default operation name is shown. Only one method per endpoint is displayed at a time for testing.
  3. Click Request.
  4. Expand Parameters to view the query or header parameters that you provided.
    1. (Optional) Click Example to view the example body, if you provided one. Enter an alternate example to test with by clicking Use Example. The provided example body is copied into the text box. You can edit the example as needed.
    2. (Optional) Click Schema to view the request body schema if you provided one.
  5. Click Response.
  6. Expand the status code area and click Example or Schema to review the example or schema for the response body, if you provided one.
  7. Click Request again to enter Authentication information.
  8. If Login Required is OFF, click Test Endpoint. Otherwise, skip this step and go to the next step.
  9. Expand Authenticationand, if Login Required is ON, select the mobile backend and its version that are associated with this API and enter your authentication credentials:
    • If Enterprise is selected, select the authentication method you want to use for testing and provide your mobile user credentials.

    • If Enterprise is selected and Single Sign-On is enabled for the associated mobile backend, select Single Sign-On as the authentication method and enter either the MCS-issued SSO OAuth token (hover over the ? icon and follow the instructions) or the third-party issued SSO token that you obtained from your trusted remote identity provider.

      For information on configuring a Single Sign-On provider, see Configuring Identity Management (SSO and OAuth).

    • If Social Identity is selected, select a social authentication provider and enter the access token that you got from your provider.

    Note:

    MCS automatically URI encodes the username and password that you enter. An error can result if the username and password entries contain special characters (that is, you’ve entered pre-URI encoded values). If you enter values for these fields that are already encoded, another layer of encoding is added. During authentication, these values are decoded once, and the original encoded values are revealed, which will fail authentication so don’t enter URI-encoded values for username and password.
  10. Click Test Endpoint.
    Click Request to see the metadata for the transaction, such as header information and the body of the request. Click Response to see the details of the response returned. The response code tells you whether or not the connection was successful.
Test each of your operations and modify them as needed to validate your endpoints. When your custom API is completed, you can go to the APIs page and check out the Implementations, Deployments, Used By, and History fields to find out how often the API is being called, what mobile backends are using it, and more. See Managing an API.

To learn how to get a Single Sign-On OAuth token, see Enterprise Single Sign-On in MCS.

To find out how to get an access token from a social authentication provider, see Getting a Facebook User Access Token Manually.

Creating Resource Types

A resource type is a partial resource definition that specifies a description and methods and their properties. Resources that use a resource type inherit its properties, such as its methods. You don't have to use a resource type, but if you find that you're defining resources with the same methods, you can increase efficiency by defining resource types to reduce the redundancy.

Using the incident report example, you might want to get reports from several departments (billing, service technicians, and clerks). For each department, you want to get a list of employees involved with a particular incident and you want the name, ID, and extension number for each employee. You can define a resource type, employee_contact that defines a GET method that retrieves all the personnel information that you need. Instead of defining an employee_contact for each branch of the company, you can apply the employee_contact resource type to each incident report resource.

Note:

Resource types can’t be used with nested resources.

You can define multiple resource types for use with the given API. Resource types are specific to the API and aren’t shared across other APIs.

Adding a resource type through the API Designer is simple:

  1. Click Types and then click New Resource Type.
    The Types page is displayed:
  2. Enter a name for the resource type.
    For example, a resource type called orderinfo could be used each time appliance parts are ordered.

    Valid resource type names are character strings and can include underscore (_) and hyphens (-). Camel case is allowed (for example, employeeContact). Don’t include special characters, such as slashes, asterisks (*), and exclamation points (!).

  3. (Optional) Add a description of the type.
  4. Enter a brief sentence that describes the purpose of the type in the Usage field, then enter a description of the type in the Description field.
    For example, a resource type called orderinfo , the usage might be: Defines a standard parts order. The description might be: Always get model’s serial number and part number.
  5. Click Definition to define the resource type in the source editor.
  6. Click Save when you’re done defining the type.
  7. (Optional) Click Test to test your resource type.
    Edit your definition as needed. When you’re finished, return to the Types page to add another type or navigate to another page in the wizard.
The resource type is added to the list of available resource types for use with the given API. To learn more about resource types, see Resource Types and Traits in the RAML specification.

Creating Resource Traits

A trait is a partial method definition that provides method-level properties such as a description, headers, query string parameters, and responses. Define traits for obtaining descriptive information like version numbers or vendor information. Methods that use one or more traits inherit those traits' properties. As with resource types, if you’re defining methods with the same attributes multiple times, then define a trait to prepopulate a method with certain attributes. You don't have to use resource traits, but they’re useful if you have several methods with the same operational structure.

Note:

You can define multiple resource traits for use with the given API. Resource traits are specific to the API and aren’t shared across other APIs.

Here's how to define a resource trait:

  1. In the API Designer, click the Traits navigation link and click New Trait.
    The Traits page is displayed:
  2. Enter a name for the trait.
    For example, a resource trait called parts-inventory could define a standard method of looking up the availability and location of specific parts.

    Valid resource trait names are character strings and can include underscores (_) and hyphens (-). Camel case is allowed (for example, applianceModel). Do not include special characters, such as slashes, asterisks (*), and exclamation points (!).

  3. Enter a brief sentence that describes the purpose of the trait in the Usage field, then enter a description of the trait in the Description field.
    For example, if you have a trait called parts-inventory, the usage might be: Apply to GET methods for all part requests. The description might be: Always determine if parts are in stock and list warehouse locations.
  4. Click Definition to define the resource trait in the source editor.
  5. Click Save so you don't lose your work.
The resource trait is added to the list of available resource traits for use with the given API. To learn more about resource traits, see Resource Types and Traits in the RAML specification.

Providing API Documentation

A good, even great API is useless without documentation describing it so others can use the API too. While the API Designer can't write that documentation for you, you can upload it through the API Designer so that the next time you or someone else selects this API from the API Catalog, a full description of the API is available (its purpose, its resources and schemas, the security policies that it uses, and helpful code comments).

  1. In the API Designer, click the Documentation navigation link and click Documentation.
  2. Enter a title for your API document.
  3. You can either manually write your API documentation using Markdown syntax in the source editor or copy and paste your documentation into the editor.

    Click Markdown Reference to see how to use Markdown. It lets you write an easy-to-read plain text that can easily be converted to structurally valid XHTML for viewing in a browser. See How Do I Write in Markdown?

    Here’s an example of part of the API documentation for the FIFIncidentReports API:

  4. Click Save so you don't lose your work.
    You can add more documentation by clicking New Title and adding content in the editor field for that document. You can replace the default title provided by entering text in the title field. Each time you click New Title, the title field and editor for the most recent document is appended below the previous document. When you click Save, only the current document is displayed. Click a title tab to view that particular document.

    To see the API documentation for a specific API, select the API from the API Catalog, click Test, and then on the Test page, click the Overview tab.

How Do I Write in Markdown?

Markdown is a simple set of syntax that you can use to produce basic formatting structures such as section heads, paragraphs, ordered and itemized lists, block quotes, and links.

Construct Markdown Output

Header:

Use hash marks (#) to denote headers

#First-Level Heading

## Second-Level Heading

### Third-Level Heading

First-Level Heading

Second-Level Heading

Third-Level Heading

Paragraph:

Separate paragraphs with one or more blank lines.

This is a paragraph.

This is a second paragraph.

This is a paragraph

This is a second paragraph.

Simple List:

Use +, -, or * followed by a space to denote list items.

List markers are interchangeable.

- list item 1

+ list item 2

* list item 3

- list item 1

- list item 2

- list item 3

Nested List:

Use +, -, or * followed by a space to denote list items and indent nested list item by exactly four spaces.

-list item 1

+ list item 1a

+ list item 1b

-list item 2

- list item1

- list item 1a

- list item 1b

- list item 2

Ordered List:

Precede each item with a number in a consecutive sequence followed by a space.

1. list item 1

2. list item 2

* list item 2a

* list item 2b

3. list item 3

1. list item 1

2. list item 2

2a. list item 2a

2b. list item 2b

3. list item 3

Emphasis Italics:

Wrap text with an asterisk (*) or single underscore.

*text*

_more text_

text

more text

Emphasis Bold:

Wrap text with two asterisks (*) or double underscores.

**text**

__more text__

text

more text

Inline code:

Use back quotes (`) around the text.

This is an `inline code` example.

This is an inline code example.

Code Block:

Indent each line by four spaces

Format a block of preformatted code:

This is a code line.

Format a block of preformatted code:

This is a code line.

Links:

Put the link text in brackets, followed immediately by the URL in parentheses.

This is an [example link](http://example.com).

This is an example link.

If you want to find out more about Markdown, see What is Markdown?

Getting Diagnostic Information

You can view the response code and returned data to determine if your endpoints are valid. A response status other than 2xx doesn't necessarily mean that the test failed. If the operation was supposed to return a null response, then the response should show a 4xx code.

For every message you send, MCS tags it with a correlation ID. A correlation ID associates your request with other logging data. The correlation ID includes an Execution Context ID (ECID) that’s unique for each request. With the ECID and the Relationship ID (RID), you can use the log files to correlate messages across Oracle Fusion Middleware components. By examining multiple messages, you can more easily determine where issues occur. For example, you can retrieve records from Oracle Fusion Middleware Logging using the call's ECID. From the Administration page, you can click Logs to view logging data.

Depending on your MCS access permissions, you or your mobile cloud administrator can view the client and server HTTP error codes for your API's endpoints on the Request History page, allowing you to see the context of the message status when you're trying to trace the cause of an error. Every message sent has a set of attributes such as the time the event occurred, the message ID, the Relationship ID (RID), and the Execution Context ID (ECID).

To learn more about getting and understanding diagnostics, see Monitoring Performance and Troubleshooting .

After you've configured your custom API, you can provide an API implementation, that is, create your own custom code and add it to your mobile backend to access the API. See Implementing Custom APIs.

API Design Considerations

When you configure your custom API, there are some things you can do to ensure you have a well-formed API, including making sure that URLs and resources are well-formed, that reasonable read and connect timeouts have been set, and, if you’re providing a RAML file, that it’s correctly configured.

Here are some things to consider when you configure your API and some detailed descriptions of more advanced constructs that you can use to refine your API.

Valid URLs

In creating your RESTful API, it's important that you define a valid URL. You can see the URL for your API as you define it from the API name that you provide and the resources and methods that you add. To ensure that you have a valid URL, it must adhere to the following best practice guidelines:

  • Provide a relevant and easily identifiable resource name. Using identifiers in your URLs make for a more understandable resource than using a query string. Which makes more sense to you, the resource name /customers/2223 or /customers/api?type=customerid=2223?

  • Resources can be grouped into a collection, so make the collection resource name consistent with the attribute names used to refer to the collection.

    For example, if an attribute is a collection of favorite bookmarks, be obvious and name the collection favoriteBookmarks instead of favoriteLinks.

  • Always make the resource names plural nouns and alternate between plural nouns and singular resource identifiers (rid): /services/1.0/items/{rid}/subitems/{rid}/

    For example: /customers/2223/orders/555

    To ensure that the API is sync-compatible, always put the identifier immediately after its related resource name as shown in the previous example, where 2223 is the designation of a specific customer and 555 is the designation of a specific order. A poorly formed URL to indicate a specific customer could look like this: /customers/orders/2223/555 or /customers/orders/locations/2223.

  • Use lowercase for resource names and use camel case for attribute names.

    For example: /services/1.0/items?limit=10&totalResults=true

  • Keep resource identifiers down to 32 characters or fewer due to the limitations of some browsers.

  • Keep URLs as short as possible. A long rambling URL is difficult to read and all the more difficult to debug.

  • When defining the URL, you can be as concrete or abstract as desired, but you should use the curly brace {} notation to indicate URI parameters. This makes the corresponding RAML more detailed and easier to test.

  • Ensure that all date formats are in the form: YYYY-MM_DD[THH:mm:ss.sss]Z.

    For example: 2014-10-07T18:35:50.123Z

  • For pagination, use the limit and offset query parameters so that the Synchronization library uses paged downloads correctly. If you don’t need to support pagination, you don’t need to specify these parameters.

  • To ensure sync compatibility, use the orderBy query parameter to specify sorting. For example: “orderBy=propA,propB:desc,propC:asc”. In this example, the default sort order is by ascending value.

    For details on designing sync-compatible custom APIs, see Making Custom APIs Synchronizable.

  • Provide values for query parameters as a URL-encoded JSON string. For example:

    [
      {
        "property":"propertyName",
        //Supports Equals, NotEquals, LessThan, GreaterThan, LessThanOrEqual,GreaterThanOrEqual
        "comparison":"Equals", 
        "value":"Must be a string",
      },
      {
        "property":"Another clause, only support ANDS not ORs",
        ...
      }
    ]

API Timeouts

Sometimes when an API fails, it’s due to a stream or connection timeout. Stream timeouts happen when, after a successful connection to the server, data is being transmitted and the network time outs before all the data can be sent or received. Connection timeouts happen when the network connection is never made.

To ensure that connectors have sufficient time to make a connection and that data can be transmitted, the HTTP read and connection timeouts should have smaller values than the API timeout.

The Network_HttpRequestTimeout value determines the amount of time spent transmitting an HTTP request before the operation times out. The default value is 40,000 ms. The value of this policy can affect your API timeout values, which should be less than the value of the policy. Note that policy values are specific to a particular environment. The value for this policy in a development environment can be different from its value in a runtime environment. Your mobile cloud administrator can increase or decrease the timeout value from the Administration tab.

If you have mobile cloud administrator privileges, then you can select an environment in the Administration view and export the policies.properties file to see a list of the current environment policies and their values. For information about API environment policies and policy settings, see Oracle Mobile Cloud Service Environment Policies. For information about environment policies in general, see Environment Policies.

API Resources

A key element of an API is the resource. A resource is the conceptual mapping to an entity or to a set of entities and is identified by its relative base URI. In other words, a resource is a thing (noun) that’s located at an address to which you want to transmit information or receive information. It has at least one method (verb) that operates on it. A method is what you use to retrieve, create, update, or delete a representation of a resource. For example, GET incidents.

A top-level resource is a resource defined at the root level (also referred to as the root resource). A resource that’s defined as a child of another resource is a nested resource. Nested resources let you specify aspects of the parent resource. A nested resource is identified by its URI relative to the parent resource URI. For example, let’s say you have a root resource defined as .../incidents, and you have a nested resource, {id}. The API definition in RAML looks like:

title: FIFIncidentReports
version: 1.0
baseURI: /mobile/custom/fif-incidentreport
protocols: [HTTPS]
mediatType: "application/json"
/incidents:
  displayName: Incident Reports
  get:
    description: |
      Retrieves all incident reports.
.
.
.
/{id}:
  uriParameters:
    id:
      displayName: id
      description: |
          The unique id of the incident report.

A resource is always preceded with a slash (/), whether it’s a root or nested resource. For information about constructing a valid RAML document, see RAML.

If you think of a resource as a collection of objects and a nested resource as an item in that collection, then your resource path shows the parent resource in plural form and a nested resource in singular form. For example:

.../mobile/custom/fif-incidentreport/incidents/{id}

The root resource is incidents and the instance of an incident is {id}. You can give the resource an easy-to-read display name on the Endpoints page. If you don't provide a display name, then the resource URI is used as the name.

A common practice when designing a resource is to have PUT and POST methods return the same objects that are sent in the request.

URI Parameters

If you want to allow API calls that change or restrict the value of the relative base URI, then you can override it by setting a base URI parameter. The URI of a resource can contain parameters, which are variable elements, for example {id}.

Like resources, parameters have a name. The RAML generated for our fif-incdentreport shows the resource parameter named id, a display name (id, although the display name doesn't have to be the same as the parameter name), and a value type (in this example, the value type is integer):

  /{id}: 
    uriParameters:  
      id: displayName: id   
      description: | 
        the unique id of the incident report  

      type: integer
      required: true
   get:
     description: |
       Retrieves the incident report with the specified id.

You place the path parameter after the resource name. Use a semicolon to separate multiple parameters. For parameters that can have multiple values, separate the values with commas.

In the example, the URI parameter /{id} is a variable that identifies a specific incident report by its ID number. The parameter contains the properties displayName and type. The URI would look like this:

.../fif-incidentreport/incidents/{id}

If the parameter, id, has a value of 1234, then the resulting URI would look like this:

.../fif-incidentreport/incidents/1234

Parameters can be added as part of the URI path as a child (nested) resource or added as a query. There are no hard and fast rules to adding parameters to the URI path versus adding parameters as a query. One possible consideration is whether the parameter is essential to the request. For example, to get data for a specific report, you would use an identifier (id) of the resource in the URI path as shown in the previous fif-incidentreport URI example.

However, if you’re using the parameter as a filter to narrow down the data, then add it in the query. For example, you would use technician as a query parameter .../fif-incidentreport/incidents?technician=joe to filter reports only by a particular technician.

Endpoint Requirements for Sync Compatibility

To ensure optimal synchronization of data when a custom API is used by the Synchronization library on a client, the custom API must include a specific set of server-side endpoints.

For example, let's say a custom API endpoint is defined that returns a collection of Department records and is consumed by a client that uses the Synchronization library. Records are retrieved from the collection endpoint, /Departments, and stored in the client’s local cache by the library. Later on, the library identifies two records in the cache that require updating because they’ve expired (/Departments/Finance and /Departments/HR).

In this case, to get the most up-to-date data, the Synchronization library retrieves only the records that need to be updated, and not the entire collection.

On the server side, via the associated Synchronization library, these endpoints are called individually on behalf of the client. The data is returned to the client in a single payload and response, saving multiple round trips for each required object.

To support this, the Synchronization library requires that the custom API includes GET methods for both the collection resource (GET /{collection}) and the object resource (GET /{collection}/{objectId}). That is, in our Department example, the following endpoints are needed:

  • GET /Departments

  • GET /Departments/{DeptId}

To go a step further, if the offline API collection objects that were retrieved can be modified, say by the addition, update, or deletion of an object, the Synchronization library calls the appropriate custom code APIs to enact the change on the objects on the server side. To support creating, updating, or deleting the object requires that the following types of endpoints are implemented on the server-side custom API:

  • GET /{collection}

  • GET /{collection}/{objectId}

  • PUT /{collection}/{objectId}

  • POST /{collection}

  • DELETE /{collection}/{objectId}

The inclusion of the PUT, POST, and DELETE operations are optional. If, for example, your application never deletes an object in a collection, you don’t need to implement the DELETE operation.

Note:

The Synchronization library doesn’t support the PATCH operation.

See Making Custom APIs Synchronizable to learn more about configuring a sync-compatible custom API.

Schemas

A JSON schema defines the structure of your API in a JSON-based data format. The JSON schema can be used to validate JSON data. You can define a schema from the Schema page. Let's look at the schema from the IncidentReports example:

{ 
        "$schema": "http://json-schema.org/draft-04/schema#", 
        "type": "array", 
        "description": "Incident Reports array", 
        "items": { 
          "type": "object", 
          "properties": { 
            "id":  { "description": "Unique id for the incident report", 
                     "type": "integer" }, 
            "title": { "description": "Title for the incident report", 
                       "type": "string" }, 
            "createdon": { "description": "Date and time of creation", 
                           "type": "string" },
            "contact": { "decription": "Contact information for customer filing the report", 
                           "type": "object",  
                           "properties": {
                             "id" : { "description": "Unique id for the customer", 
                                      "type" : "string" }, 
                             "name" : { "description": "First and last name of contact",
                                       "type" : "string" }, 
                             "street": { "description": "Street address of contact", 
                                       "type" :  "string"}, 
                             "city" : { "description": "City of contact", 
                                       "type" : "string"},
                             "postalcode" : { "description" : "Postalcdoe of contact",
                                               "type": "string" }
                             }
                  },
             "status" : { "description": "The current status of the incident",
                          "type" : "string" },
             "priority" : { "description": "The current priority of the incident", 
                          "type" : "string" }, 
             "driveTime" : {"description" : "Calculated field based on location",
                          "type" :  "integer"},
             "imageLink" : { "description" : "Link to image from Storage",
                           "type": "string" }
            },
          }
      }

This schema contains the following keywords:

  • $schema: denotes that this schema is based on the draft v4 specification. It must be located at the root of the JSON schema. You should always include this keyword in your JSON schema.

  • type: defines a JSON constraint, so the data must be an array.

  • description: describes the contents of the schema.

  • items: define the items in the array. In an incident report, we want to assign attributes to each report. In this example, all items are of type object and each object has a set of properties, such as report ID, title, contact info, status, priority level, etc.

For a complete list of keywords to use in your JSON schema, see http://json-schema.org/.

To add a schema for your API, see Providing a Schema.

RAML

When you create an API using the MCS interface, the API definition is stored as a RAML document. RAML is a simple efficient way to describe RESTful APIs. REST stands for Representational State Transfer (REST) and is a way to perform basic operations (create, read, update or delete) information on a server using simple HTTP calls.

You can also upload a RAML document that you create from scratch into the API Designer. The API Designer takes the input that you provide and creates a RAML file that documents the contents of the custom API. Note that the RAML defines only the API itself, not the implementation of the API. You must create custom code using JavaScript to implement the API. For information on how to implement an API, see Implementing Custom APIs.

Note:

The feature to upload a RAML document isn’t available if you came to the API page by clicking APIs from the navigation list of a mobile backend.

If you upload a RAML file, then the values for the required Name fields are extracted from the RAML file. You still have to add the short description. At a minimum, your RAML file must include the API name, a base URI (/mobile/custom/apiname), and a version number.

For your RAML file to be valid, it must specify a media type, base URI, the HTTPS protocol, and a version number:

#%RAML 0.8
---
title: api_title
version: 1.0
protocols: [HTTPS]
baseURI: /mobile/custom/api_name
mediaType: application/json

Note:

MCS requires the HTTPS protocol for custom APIs. If you upload a RAML document that configures the API using the HTTP protocol, then it’s automatically edited to use HTTPS.

For new a API, a default version of 1.0 is automatically applied when you save the configuration (unless the mobile cloud administrator has changed the value of the Asset_DefaultInitialVersion environment policy). However, if you upload an API configuration, then the version value displayed is taken from the file.

Note:

The version value uses a specific format. Versions are specified with an integer. For example, in your RAML file specifying version: 2.0 is valid while version: v2.0 isn’t.

RAML lets you define resource types and traits for describing resources and methods, which results in a more succinct RESTful API by reducing repetition in the design. The principle components of a RAML (.raml) document are:

  • Basic API information consisting of:

    • API Display Name: the easy—to—read name of the API, which appears in the API list (for example, FIFIncident Reports)

    • Base URI: The address of the resource (/mobile/custom for custom APIs)

    • API Name: name of the API (fif-incidentreport) in the configuration

    • Short description: Brief description of your API

  • Resource types and traits, which allow you to characterize resources to avoid unnecessary repetition in the API definition

  • Resources (the conceptual mappings to one or more entities), resource methods, and schema

To ensure that your RAML document is correctly configured, follow these tips:

  • Although RAML allows both HTTP and HTTPS protocols, MCS requires the HTTPS protocol for custom APIs. If you upload a RAML document that configures the API using the HTTP protocol, then it’s automatically edited to use HTTPS.

  • If you define a top-level resource with an empty relative URI (that is, /:), then you can’t add a subresource to it.

    An error message will alert you that the structure is invalid. For example, the following resource definitions will fail:
    /:
      /reports:
    You need to make reports a top-level resource:
    /:
    /reports:
  • Top-level resources shouldn’t contain empty relative URI subresources, for example:
    /books:  
      /:
  • Avoid creating duplicate paths, for example:
    /reports/{id}:
    /reports:
      /{id}:
    Multiple subresources in the resource name are valid. For example:
    /reports:
      /county/branchid/reportissue:
  • Add comments only in a property’s description: field. Adding a comment using a comment line (for example, #report issue by technician) is not supported by the RAML source editor. Comments added in a comment line are stripped out by the parser.

For a thorough discussion about RAML, see http://raml.org/.

Editing a Custom API

You can always edit an API as long as it’s in the Draft state. A published API can’t be changed.

To edit a custom API:
  1. Make sure that you’re in the environment containing the API you want to edit.
  2. Click open the side menu icon and select Applications > APIs from the side menu.
    Now that at least one custom API exists, the APIs page is displayed.
  3. Select the draft API that you want to edit and click Open.

    You can filter the list by version number or status. You can also sort the list alphabetically by name or by last modified date.

  4. Edit the fields for general information, resource, schemas, traits, types, and security policies as needed.
    Each time you create a method for a resource, an icon for the method appears at the top of the Methods page. Click on one of these icons to go directly to the method definition:
    On the Resources page, icons for the methods defined for the resource are displayed below the Methods navigation link. You can quickly see what types of methods have been defined for a resource. Click on an icon to go the method definition:

    Remember you can always click Save and Close to save your current changes and finish the rest of your changes later.

  5. Save your changes if you didn't select the option to always save the configuration before testing when you created the API.
  6. Test your changes.

Your edited version is still in a Draft state and you can continue to edit your custom API until you’re satisfied with the configuration. At that point, you’re ready to publish your custom API. See Publishing a Custom API. If you need to make a change to a published API, you’ll have to create a new version of it. See Creating a New Version of an API.

After you’ve published it, you can then deploy your API to other environments. See API Lifecycle for information on specific parts of an API lifecycle. For general information about lifecycle in MCS, see Lifecycle.

Video: End-to-End Custom API Demo

To see the process of designing and developing a custom API, including how it fits in with a mobile backend and a connector, take a look at this video:

Troubleshooting Custom APIs

When an incorrect value is entered in a field, a message window displays the error and, depending on the field, the correct syntax or value type to use. In some cases (such as when a malformed schema or RAML is uploaded), the error message includes a Show Details link that displays a description of the error. See Viewing Log Messages.

To learn more about common errors that can occur when you configure custom code, see Common Custom Code Errors.

When troubleshooting an unexpected result, consider that the cause might be due to a rerouting of the call to the mobile backend as described in Making Changes After a Backend is Published (Rerouting). If the mobile backend was rerouted, check to see if the following conditions were met:
  • If the API was accessed using social identity, then the access token of the provider that was entered in the Authentication header must be the access token of the provider of the target mobile backend (that is, the mobile backend to which the original mobile backend was redirected).

  • If the API was accessed by a mobile user, then the user must be a member of the realm that is associated with the target mobile backend (the mobile backend to which the original mobile backend is being redirected).