Skip to content
vtiffenberg edited this page Nov 17, 2014 · 7 revisions

Accessing the API

The APIs can authenticate with HTTP basic, for which you must provide a user email and password, or through the unified system for InSTEDD Platform which is handled through the GUISSO gem.

For long-term system integration, you may want to create a user that is only used for API purposes so it is less affected by resetting passwords, permission changes, etc than a person.

API in within internal staging releases is subject to changes without versioning. Changes to public releases will be versioned and documented. The documentation below may be out of sync with any specific deployed version in staging.

If you have questions or find issues please feel free to contact discuss here: InSTEDD Technology Users Community (Google Group)

Getting your collection ID

Unless you want to use discovery APIs, you can get started by

  1. Going to your collection property tabs
  2. Under the 'Overview' tab look at the API Access section
  3. You will have links to the query API, and you can see your collection ID in that URL.

You can get your collections by querying

  • /api/collections.json
[{"created_at":"2012-03-27T07:40:06Z","description":"","id":350,"lat":"-2.002419","lng":"29.933107","name":"Hospitals","public":null,"updated_at":"2012-03-28T07:58:02Z"}]

Format

The format can be specified by the extension of the request. For example,

  • /api/collections/350.json
  • /api/collections/350.rss
  • /api/collections/350.csv

The GeoJSON format has a different URL:

  • /api/collections/350/geo.json

GeoRSS

The RSS return format fulfils the GeoRSS specification using the //http://www.w3.org/2003/01/geo/wgs84\_pos// namespace, and latitude and longitude fields are presented in geo:lat and geo:long elements corresponding to that namespace. This makes it easy to consume the data from GeoRSS compatible tools. Keep in mind the consuming application will need to provide the login credentials unless the collection has a public layer.

Queries

Note: For these examples we will assume you have an Collection ID of 350

Getting all sites in a collection: /api/collections/350.json

Filtering

ResourceMap allows filtering sites by every kind of property defined in the collection. It also allows counting, sorting and paging.

More information here

A count of items in the collection can be obtained by calling:

  • /api/collections/350/count.json

Getting one site

You can retrieve only one item by ID the following way:

  • /api/sites/:id.json
  • /api/sites/:id.rss

Note: The ID field is the internal system ID of the item, not some field you created and treat as an ID field.

Versioning

ResourceMap stores a site version every time a change is made. These versions are called "histories". Each history has an autoincremental version number and valid_from/valid_to fields that indicate the from/to dates in which this version was the current one. Each history contains the complete site information, and not only the changed values. It also includes the email of the user that performed the last update in the site.

To get all histories of a site:

  • GET /api/collections/:collection_id/sites/:site_id/histories.json

To get a particular site's version:

  • GET /api/collections/:collection_id/sites/:id/histories.json?version=:version_number

Note: You need to be the admin of the collection to be allowed to query site histories

Sample return data:

GET to /api/collections/428/sites/119815/histories.json?version=3

Sample return data:

GET to /api/collections/428/sites/119815/histories.json?version=3

[{
  collection_id: 428,
  name: "angola",
  lat: "-12.892942",
  lng: "16.776647",
  created_at: "2013-10-29T20:07:07Z",
  updated_at: "2013-10-31T21:14:42Z",
  properties: {
    1561: 2.34,
    1562: 2,
    1563: true,
    1564: 2,
    1565: [
      3,
      1,
      2
    ],
    1573: "100001-8",
    1574: "2"
  },
  valid_since: "2013-10-29T20:07:07Z",
  valid_to: "2013-10-31T21:14:42Z",
  site_id: 119815,
  uuid: "cc33e476-4879-4096-a5e5-1baf8fd2af0b",
  version: 3,
  user: "[email protected]"
}]

Metadata

Note: You need to be the admin of the collection to be allowed to query the metadata information

You can get a definition of your layer metadata here:

  • /api/collections/350/layers.json

This will return all metadata about fields (codes, lookup values and codes, etc) in the collection with ID = 350, grouped in layers.

For more specific actions follow this link

Security Info

You can get which users have access to which layers here:

  • /api/collections/350/memberships.json

This will return all the users that have access to the system collection with ID= 350, and their permissions to read and write to different layers and sites. Of course, accessing this information is only possible if the login used in the request has permissions as an owner of the collection.

This is a sample return data for membership's query:

[
  {"user_id":2,"user_display_name":"[email protected]","admin":true,"layers":[],"sites": {"read":null,"write":null}},
  {"user_id":1,"user_display_name":"[email protected]","admin":false,
    "layers":[
      {"layer_id":53,"read":true,"write":false},
      {"layer_id":56,"read":true,"write":true},
      {"layer_id":58,"read":true,"write":false}],
    "sites":{
      "write":{
        "all_sites":false,
        "some_sites":[
          {"id":"8376","name":"Site 3"}]},
      "read":{"all_sites":true,"some_sites":[]}}},
  {"user_id":7,"user_display_name":"[email protected]","admin":false,
    "layers":[],
    "sites":{
      "read":{
        "all_sites":false,
        "some_sites":[
          {"id":"8376","name":"Site 3"},
          {"id":"11487","name":"Site 4"}]},
      "write":{
        "all_sites":false,
        "some_sites":[
          {"id":"11487","name":"Site 4"}]}}}
]

Example Return Data

Here are some examples so you can see the JSON and RSS formats:

  • /api/collections/350.json
{
    "name": "Hospitals",
    "totalPages": 1,
    "sites": [
        {
            "id": 17442,
            "name": "Sunshine Hospital",
            "createdAt": "2012-03-28T07:55:56+00:00",
            "updatedAt": "2012-03-28T07:55:56+00:00",
            "lat": -1.901301,
            "long": 30.418267,
            "properties": {
                "Color": "1",
                "Services": [
                    "XR",
                    "OBG"
                ],
                "NUMBEDS": "20",
                "MGR": "Mr. Richard"
            },
            "groups": [ ]
        },
        {
            "id": 17443,
            "name": "Butare Family Hospital",
            "createdAt": "2012-03-28T07:57:05+00:00",
            "updatedAt": "2012-03-28T07:57:05+00:00",
            "lat": -2.602733,
            "long": 29.737324,
            "properties": {
                "Color": "1",
                "Services": [
                    "XR"
                ],
                "NUMBEDS": "30",
                "MGR": "Mr. Daniel"
            },
            "groups": [ ]
        },
        {
            "id": 17444,
            "name": "Musanze Hospital",
            "createdAt": "2012-03-28T07:58:01+00:00",
            "updatedAt": "2012-03-28T07:58:01+00:00",
            "lat": -1.503223,
            "long": 29.643731,
            "properties": {
                "Color": "3",
                "Services": [
                    "XR",
                    "OBG",
                    "TR"
                ],
                "NUMBEDS": "55",
                "MGR": "Mrs. Liz"
            },
            "groups": [ ]
        }
    ]
}
  • /api/collections/350.rss
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:rm="http://resourcemap.instedd.org/api/1.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Hospitals</title>
    <item>
      <title>Sunshine Hospital</title>
      <pubDate>2012-03-28T07:55:56+00:00</pubDate>
      <link>http://resmap-stg.instedd.org/api/sites/17442.rss</link>
      <guid>http://resmap-stg.instedd.org/api/sites/17442.rss</guid>
      <geo:lat>-1.901301</geo:lat>
      <geo:long>30.418267</geo:long>
      <rm:properties>
        <rm:Color>1</rm:Color>
        <rm:Services>["XR", "OBG"]</rm:Services>
        <rm:NUMBEDS>20</rm:NUMBEDS>
        <rm:MGR>Mr. Richard</rm:MGR>
      </rm:properties>
    </item>
    <item>
      <title>Butare Family Hospital</title>
      <pubDate>2012-03-28T07:57:05+00:00</pubDate>
      <link>http://resmap-stg.instedd.org/api/sites/17443.rss</link>
      <guid>http://resmap-stg.instedd.org/api/sites/17443.rss</guid>
      <geo:lat>-2.602733</geo:lat>
      <geo:long>29.737324</geo:long>
      <rm:properties>
        <rm:Color>1</rm:Color>
        <rm:Services>["XR"]</rm:Services>
        <rm:NUMBEDS>30</rm:NUMBEDS>
        <rm:MGR>Mr. Daniel</rm:MGR>
      </rm:properties>
    </item>
    <item>
      <title>Musanze Hospital</title>
      <pubDate>2012-03-28T07:58:01+00:00</pubDate>
      <link>http://resmap-stg.instedd.org/api/sites/17444.rss</link>
      <guid>http://resmap-stg.instedd.org/api/sites/17444.rss</guid>
      <geo:lat>-1.503223</geo:lat>
      <geo:long>29.643731</geo:long>
      <rm:properties>
        <rm:Color>3</rm:Color>
        <rm:Services>["XR", "OBG", "TR"]</rm:Services>
        <rm:NUMBEDS>55</rm:NUMBEDS>
        <rm:MGR>Mrs. Liz</rm:MGR>
      </rm:properties>
    </item>
  </channel>
</rss>

GeoJson Example with one site only:

{
   "type":"Feature",
   "geometry":null,
   "properties":{
      "features":{
         "type":"FeatureCollection",
         "features":[
            {
               "type":"Feature",
               "geometry":{
                  "type":"Point",
                  "coordinates":[
                     30.418267,
                     -1.901301
                  ]
               },
               "id":17442,
               "properties":{
                  "name":"Sunshine Hospital",
                  "createdAt":"2012-03-28T07:55:56+00:00",
                  "updatedAt":"2012-05-08T14:42:25+00:00",
                  "properties":{
                     "Color":"1",
                     "Services":[
                        "XR",
                        "OBG"
                     ],
                     "NUMBEDS":"20",
                     "MGR":"Mr. Richard"
                  }
               }
            }
         ]
      },
      "name":"Hospitals",
      "count":3,
      "totalPages":1
   }
}

Activity Stream

You can query the activity rss feed for your collections via API.

The URL is /api/activity.rss

This feed will show all user's activity in all collections in which you are a member.

Optionally you can specify in what kind of activities and in which collections are you interested.

  • /api/activity.rss?collection_ids[]=32&collection_ids[]=31 : filters all kind of activity in collection with internal id 32 or 31

The options for filtering kind of activity are:

  • collection,created
  • collection,csv_imported
  • collection,imported
  • layer,created
  • layer,changed
  • layer,deleted
  • site,created
  • site,changed
  • site,deleted

For example:

  • /api/activity.rss?kinds[]=site,deleted&kinds[]=layer,deleted : filters sites and layer delete action of all users in all collections.

You can also combine collection_ids and kinds in the same query.

Update Site

Single property update in Site

You can update a single property in a Site you should do a POST to:

  • /api/sites/:site_id/update_property.json

Note: site_id is the internal system ID of the site

And you should pass the parameters you want to update:

  • ?es_code=350&value=Mr. Richard

350 is the property internal ID and Mr. Richard is the new value for the property

To find the ID of the field you need to update, query for layers or fields of your collection. The es_code required is the numerical ID of the field, not the code or the name. More information on querying metadata here: API for Metadata queries

Param format

  • Text Fields: ?es_code=350&value=Changed Text

  • Numeric Fields: ?es_code=350&value=1234

  • Select One Fields: ?es_code=350&value=2 // 2 is the internal ID for the option

  • Select Many Fields: ?es_code=350&value[]=2&value[]=1 // 1 and 2 are the internal ID for the options

  • Hierarchy Fields: ?es_code=350&value[]=2 // 2 is the internal ID for the hierarchy

  • Date Fields: ?es_code=350&value[]=12/26/2012 // The date is in MM/DD/YYYY format

  • Site Fields: ?es_code=350&value=12456 // 12456 is the referred Site internal ID

  • User Fields: ?es_code=350&value=[email protected] // [email protected] is the user's email

  • Email Fields: ?es_code=350&value=[email protected]

  • Phone Fields: ?es_code=350&value=15555555555

Deleting values

For deleting the field's value, simply do not pass the parameter "value".

  • ?es_code=350 : will delete the value for property with internal ID = 350.

This works for all field's types.

Changing Site's name or location - OBSOLETE

For changing name or location, you should do a PUT to:

  • /collections/:collection_id/sites/:site_id.json

With parameters:

"site": {"name": "New Site Name"}

or:

"site": {"lat": -12.834253993970767, "lng": 30.15640980316266}

Full update - OBSOLETE

For changing more than one property, you should do a PUT to

  • /collections/:collection_id/sites/:site_id.json

With parameters:

{"site": {"id": :site_id, "name": "New Site Name", "lat": -12.83425399397077, "lng": 30.15640980316266, "properties": {"206": "new text value", "207": "12345", "208": 2}}}

Each property value format depends on the field's type. The format is specified in "Param format" section.

Partial update

The action you need to use is

  • /api/sites/:site_id/partial_update.json via POST

Through this action those parameters included in the request are updated, but not the ones that are not present.

The format of the parameters are the same of in "Full Update" section above.

Bulk update

All sites matching the search parameters will be updates according to an updates hash.

POST to

  • /api/collections/:collection_id/update_sites

with the collection's id, those filters you want to select sites to update from and an updates hash for those properties to be changed as parameters.

Example:

{"id" => :collection_id, "name" => 'Regional Hospital', "updates" => {"properties" => { "active" => true }}}

Create Site

You can create a new site by issuing a POST to:

  • /api/collections/:collection_id/sites.json

Example URL:

  • /api/collections/485/sites.json

Authentication mechanism: Basic (see Accessing the API)

Params

site (required): a JSON object sent as form-data. Sites have some built-in fields (available in every site of every collection in Resource Map) and others which are collection specific.

Built-in fields are:

  • name (text): the name of the site to be created. Required.
  • lat (decimal): latitude of the site to be created. Optional.
  • lng (decimal): longitude of the site to be created. Optional.

Collection specific site fields are inside the properties property. Since there are different types of fields (text, numeric, date, etc.), the validation criteria for each value provided inside the properties field varies.

Collection specific site fields are of the form "FIELD_ID":"VALUE", where FIELD_ID is an integer. To retrieve field ids of your collection specific site fields see API for Metadata queries.

Request

Here's an example raw HTTP request that creates a site on an example collection:

POST /collections/485/sites.json HTTP/1.1
Host: resourcemap.instedd.org
Authorization: Basic (YOUR BASIC AUTH ENCODED CREDENTIALS)
Cache-Control: no-cache

----WebKitFormBoundaryE19zNvXGzXaLvS5C
Content-Disposition: form-data; name="site"

{"name":"New Site","lat":-12.83425399397077,"lng":30.15640980316266,"properties":{"2000":"new text value","2001":"12345","2002":"2"}}
----WebKitFormBoundaryE19zNvXGzXaLvS5C

Remarks:

  • Notice the format of the Authorization header, which is where we state that we're using Basic Auth.
  • Content-Disposition is where you specify that you're sending a form-data param.
  • The param name is specified as name="site".
  • The site JSON object is built as discussed above. Pay special attention to the properties field: in this case, the request will only succeed if the target collection has specific fields with ids 2000, 2001 and 2002.

Response

If the request to create a site succeeds, Resource Map will return a JSON object with the complete representation of the site just created.

{
    "collection_id": 485,
    "created_at": "2013-11-20T20:06:35Z",
    "id": 116195,
    "id_with_prefix": "NB3",
    "lat": "-12.83425399397077",
    "lng": "30.15640980316266",
    "location_mode": "automatic",
    "name": "New Site",
    "properties": {
        "2000": "new text value",
        "2001": 12345,
        "2002": 2
    },
    "updated_at": "2013-11-20T20:06:35Z",
    "uuid": "29e6f5bb-d072-4a20-9fb1-54bf04589d57",
    "version": 1
}

Delete Site

For deleting a site, do a DELETE to:

  • api/sites/:site_id

Metadata Update

You should be a collection admin for being able to modify metadata.

Creating new layer

To create a new layer, do a POST to:

//Note: You need to set the Content-Type Header to "application/json"

  • /api/collections/:collection_id/layers.json

Parameters:

{
   "layer":{
      "name":"New Layer",
      "ord":"1",
      "fields_attributes":{
         "0":{
            "name":"Text Field",
            "code":"text_field_code",
            "kind":"text",
            "ord":"1"
         },
         "1":{
            "name":"Numeric Field",
            "code":"numeric_field_code",
            "kind":"numeric",
            "ord":"2"
         },
         "2":{
            "name":"Select One",
            "code":"select_field_one_code",
            "kind":"select_one",
            "ord":"3",
            "config":{
               "options":{
                  "0":{
                     "id":"1",
                     "code":"opt_1_code",
                     "label":"Option 1 Label"
                  },
                  "1":{
                     "id":"2",
                     "code":"opt_2_code",
                     "label":"Option 2 Label"
                  }
               }
            }
         },
         "3":{
            "name":"Select Many",
            "code":"select_field_many_code",
            "kind":"select_many",
            "ord":"4",
            "config":{
               "options":{
                  "0":{
                     "id":"1",
                     "code":"opt_1_code",
                     "label":"Option 1 Label"
                  },
                  "1":{
                     "id":"2",
                     "code":"opt_2_code",
                     "label":"Option 2 Label"
                  }
               }
            }
         },
         "4":{
            "name":"Hierarchy ",
            "code":"hierachy_field_code",
            "kind":"hierarchy",
            "ord":"5",
            "config":{
               "hierarchy":{
                  "0":{
                     "order":"1",
                     "id":"code_1",
                     "name":"Dad",
                     "sub":{
                        "0":{
                           "order":"2",
                           "id":"code_2",
                           "name":"Son"
                        },
                        "1":{
                           "order":"3",
                           "id":"code_3",
                           "name":"Bro"
                        }
                     }
                  }
               }
            }
         },
         "5":{
            "name":"Date ",
            "code":"date_field_code",
            "kind":"date",
            "ord":"6"
         },
         "6":{
            "name":"Site",
            "code":"site_field_code",
            "kind":"site",
            "ord":"7"
         },
         "7":{
            "name":"User",
            "code":"user_field_code",
            "kind":"user",
            "ord":"8"
         },
         "8":{
            "name":"Email",
            "code":"email_field_code",
            "kind":"email",
            "ord":"9"
         },
         "9":{
            "name":"Phone",
            "code":"phone_field_code",
            "kind":"phone",
            "ord":"10"
         },
         "10":{
            "ord":"11",
            "name":"Identifier",
            "code":"identifier_field_code",
            "kind":"identifier",
            "config":{
               "context":"field_context",
               "agency":"field_agency"
            }
         }
      }
   }
}

This will create a new field for each type.

Updating existing Layer

To update an existing layer, you should do a PUT to:

  • /api/collections/:collection_id/layers/:layer_id.json

Note: You need to set the Content-Type Header to "application/json"

Note: In this example we are assuming that the layer_id of the layer you want to update is 59 and the field's ids are form 241 to 250. All ids should correspond to existing layers and fields.

Parameters:

{
   "layer":{
      "id":"59",
      "name":"Existing Layer",
      "ord":"1",
      "fields_attributes":{
         "0":{
            "id":"241",
            "name":"Text Field New Name",
            "code":"text_field_code",
            "kind":"text",
            "ord":"1",
            "layer_id":"59"
         },
         "1":{
            "id":"242",
            "name":"Numeric Field",
            "code":"numeric_field_code",
            "kind":"numeric",
            "ord":"2",
            "layer_id":"59"
         },
         "2":{
            "id":"243",
            "name":"Select One",
            "code":"select_field_one_code",
            "kind":"select_one",
            "ord":"3",
            "layer_id":"59",
            "config":{
               "options":{
                  "0":{
                     "id":"1",
                     "code":"opt_1_code",
                     "label":"Option 1 Label"
                  },
                  "1":{
                     "id":"2",
                     "code":"opt_2_code",
                     "label":"Option 2 Label"
                  }
               }
            }
         },
         "3":{
            "id":"244",
            "name":"Select Many",
            "code":"select_field_many_code",
            "kind":"select_many",
            "ord":"4",
            "layer_id":"59",
            "config":{
               "options":{
                  "0":{
                     "id":"1",
                     "code":"opt_1_code",
                     "label":"Option 1 Label"
                  },
                  "1":{
                     "id":"2",
                     "code":"opt_2_code",
                     "label":"Option 2 Label"
                  }
               }
            }
         },
         "4":{
            "id":"245",
            "name":"Hierarchy ",
            "code":"hierachy_field_code",
            "kind":"hierarchy",
            "ord":"5",
            "layer_id":"59",
            "config":{
               "hierarchy":{
                  "0":{
                     "order":"1",
                     "id":"code_1",
                     "name":"Dad",
                     "sub":{
                        "0":{
                           "order":"2",
                           "id":"code_2",
                           "name":"Son"
                        },
                        "1":{
                           "order":"3",
                           "id":"code_3",
                           "name":"Bro"
                        }
                     }
                  }
               }
            }
         },
         "5":{
            "id":"246",
            "name":"Date ",
            "code":"date_field_code",
            "kind":"date",
            "ord":"6",
            "layer_id":"59"
         },
         "6":{
            "id":"247",
            "name":"Site",
            "code":"site_field_code",
            "kind":"site",
            "ord":"7",
            "layer_id":"59"
         },
         "7":{
            "id":"248",
            "name":"User",
            "code":"user_field_code",
            "kind":"user",
            "ord":"8",
            "layer_id":"59"
         },
         "8":{
            "id":"249",
            "name":"Email",
            "code":"email_field_code",
            "kind":"email",
            "ord":"9",
            "layer_id":"59"
         },
         "9":{
            "id":"250",
            "name":"Phone",
            "code":"phone_field_code",
            "kind":"phone",
            "ord":"10",
            "layer_id":"59"
         }
      }
   }
}

Deleting a Layer

To delete an existing layer you should do a DELETE to:

  • /api/collections/:collection_id/layers/:layer_id

Security Info Update

You should be a collection admin for being able to modify permissions.

Creating New Membership

To create a new membership to a collection for a user, do a POST to:

Parameters: {"email"=>"[email protected]", "collection_id"=>":collection_id"}

The email must be that of an existing user in the system.

This will return the operation status and the user_id:

{"status":"added","user_id":6,"user_display_name":"[email protected]"}

Setting admin permission

After creating the membership for the user, if you want to make them collection admin you should do a POST to:

  • /api/collections/:collection_id/memberships/:user_id/set_admin.json

Revoking admin permission

Revoking admin permission is similar: Do a POST to:

  • /api/collections/:collection_id/memberships/:user_id/unset_admin.json

Setting layer access

Users can have read and/or write permission to a collection's layer.

A POST to:

  • /api/collections/:collection_id/memberships/:user_id/set_layer_access.json

With parameters:

{"layer_id"=>"58", "verb"=>"read", "access"=>"true" }

Will create a read permission for the user with internal ID = :user_id to the layer with internal ID = 58 of the collection with internal ID = :collection_id. This means that they will be able to see all site's properties inside the layer 58, but won't be able to change them.

With parameters:

{"layer_id"=>"58", "verb"=>"write", "access"=>"true"}

Will create a write permission for the user with internal ID = :user_id to the layer with internal ID = 58 of the collection with internal ID = :collection_id. This means that theyable to modify all site's properties inside the layer 58.

Revoking layer access

You need to do a POST to

  • /api/collections/:collection_id/memberships/:user_id/set_layer_access.json

With parameters:

{"layer_id"=>"58", "verb"=>"read", "access"=>"false" }

Or

{"layer_id"=>"58", "verb"=>"write", "access"=>"false"}

Removing a user from a collection

To delete a user's membership from a collection, do a DELETE to:

  • /api/collections/:collection_id/memberships/:user_id.json

Setting site access - OBSOLETE

For setting access to all layers in an specific site to a user, you should do a POST to:

  • /collections/:collection_id/sites_permission

With parameters:

{ 
  "write"=> 
    {"all_sites"=>"false","some_sites"=>
      {"0"=>{"id"=>"8376","name"=>"Site 3"}
    }
  }
}

This means that the user with internal ID=1 will be able to see all properties of sites 3 and 4 (with internal IDs = 8376 and 11487) but will be only able to modify the Site 3's data.