Ningo provides an API to place metadata that provide meaning to beacons in known locations around the world. It allows third party apps to use a public API to discover and use these location data. It also provide APIs for third parties to submit new metadata.

Ningo Mobile SDKs

Ningo provides Android and iOS mobile SDKs to make it easy to access the database from your apps.

Data sources

The initial seed data source is designed to come from

API documentation

The WikiBeacon API uses Rest web services. The examples below show using a Unix command line utility called curl to make the requests and return data. Web service clients may be created using a number of programming languages and technologies.

Getting started in 3 easy steps

  1. Create an account.

    See the Creating a New User Via the API section below to create your own account. You may also create an account through the website at

  2. Log in to the API

    Using the credentials obtained from step 1, log in to create a temporary API auth token. This token will be valid for 24 hours:

    $ curl -i -XPOST -H "Content-Type: application/json" -d '{"email":"","password":"xxxxxxxx"}'
    HTTP/1.1 200 OK
    Server: Cowboy
    Date: Wed, 29 Mar 2017 21:14:20 GMT
    Connection: keep-alive
    X-Frame-Options: SAMEORIGIN
    X-Xss-Protection: 1; mode=block
    X-Content-Type-Options: nosniff
    Content-Type: application/json; charset=utf-8
    Etag: W/"d06d7264a58b218419a95fcccffef456"
    Cache-Control: max-age=0, private, must-revalidate
    X-Request-Id: bf1db7ee-0c09-4fec-90ae-a59fbe9e010b
    X-Runtime: 0.081724
    Transfer-Encoding: chunked
    Via: 1.1 vegur

Note that you can also create a longer-term read-only auth token which lasts for 100 years. This is suitable for embedding in a mobile app for use with the Ningo SDK. The app would then be able to query beacon data using the SDK, but not write changes. If writing is needed, the app user would need to use the mobile SDK to authenticate and get a read-write token.

 $ curl -i -XPOST -H "Content-Type: application/json" -d '{"email":"","password":"xxxxxxxx", "readonly": "true"}'
 HTTP/1.1 200 OK
 Server: Cowboy
 Date: Wed, 29 Mar 2017 21:14:20 GMT
 Connection: keep-alive
 X-Frame-Options: SAMEORIGIN
 X-Xss-Protection: 1; mode=block
 X-Content-Type-Options: nosniff
 Content-Type: application/json; charset=utf-8
 Etag: W/"d06d7264a58b218419a95fcccffef456"
 Cache-Control: max-age=0, private, must-revalidate
 X-Request-Id: bf1db7ee-0c09-4fec-90ae-a59fbe9e010b
 X-Runtime: 0.081724
 Transfer-Encoding: chunked
 Via: 1.1 vegur

 {"auth_token":"akL9eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE0OTA5MDg0NjB9.bjmSpLI_bV30B_M6brEHLQEUac_fqGJOEOmj6urmJFc", "readonly": true}
  1. Request data for a single beacon

    Beacon records may be fetched by the composite key of their multi-part identifier and the beacon type, all concatenated by underscores. The example below shows how to query the data for a record of iBeacon type with a three part identifier of 2F234454-CF6D-4A0F-ADF2-F4911BA9FFA6 1 1:

    curl -i -XGET -H 'Authorization: Token token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE0OTA5MDg0NjB9.bjmSpLI_bV30B_M6brEHLQEUac_fqGJOEOmj6urmJKg"'
    HTTP/1.1 200 OK
    X-Frame-Options: SAMEORIGIN
    X-XSS-Protection: 1; mode=block
    X-Content-Type-Options: nosniff
    Content-Type: application/json; charset=utf-8
    ETag: W/"886d54a1f20c77fecb65d602f939c0f9"
    Cache-Control: max-age=0, private, must-revalidate
    X-Request-Id: fad1cf3b-dab1-488d-8a8b-91eb89565c8d
    X-Runtime: 0.005683
    Transfer-Encoding: chunked
    {"beacon":{"identifier":"2f234454-cf6d-4a0f-adf2-f4911ba9ffa6_1_1_ibeacon","first_identifier":"2f234454-cf6d-4a0f-adf2-f4911ba9ffa6","beacon_type":"ibeacon","wikibeacon_datum":{"latitude":"38.93","longitude":"-77.0","country":"United States","country_code":null,"postcode":null,"state":"Nebraska","state_district":null,"city":"Omaha","suburb":null,"road":null,"house_number":null,"first_detected_at":"2015-09-29T17:52:35.341Z","last_detected_at":"2015-10-01T17:52:43.407Z"}}}

Additional API examples


The API allows you to create and update beacon records with attached metadata. The metadata consists of a number of required and optional fields. Submissions of metadata that do not match the schema will be rejected.

The beacon metadata schema is versioned, meaning that the metadata format is subject to change in the future. The active schema may be queried by version over the API with a request like the following:


The above response shows a JSON formatted schema definition showing required and optional elements in a standard IETF format. Replacing the "latest" at the end of the request with a number will return that schema version.

An example of a fully populated metadata record looks like this:

    "location": { "longitude": 38.93, "latitude": -77.22, "altitude": 122.0, "haccuracy": 50.0, "vaccuracy": 50.0, "type": "wgs84"},
    "radius": 50.0,
    "loctype": "outdoor",
    "categories": [ "Shopping Mall", "Main Entrance" ],
    "info": [
        "lang": "en",
        "value": "Shops at National Place",
        "description": "Indoor mall in historic National Press Club building."
        "lang": "en",
        "value": "1350 E Street NW",
        "description": "Address of entrance"
  "properties": {

The metadata object is optional, but when present, version 1 is made up of the following child objects:

location (required): Indicates the geographic coordinates where the beacon is located. This is a required metadata object, as beacons without known fixed locations are not eligible for inclusion in this database. The latitude and longitude are expressed in degrees. The other fields are optional. The altitude field is expressed in meters and haccuracy and vaccuracy are also expressed in meters and represent the estimated error rate of the latitude/longitude/altitude, if known. These accuracy fields are often provided by GPS and other location technologies. The type field is alphanumeric and represents the geodetic model of the coordinate system used (e.g. wgs84, grs80), if known.

radius (optional): Indicates the transmission radius of the beacon measured in meters.

loctype (optional): Valid values are either "indoor" or "outdoor".

categories (optional): An array of string tags that may be useful to give context to the placement of the beacon. Any string value is legal.

info (optional): An array of human-readable descriptors for the beacon's location. These should be useful for communication to a person who discovers the beacon. All fields are required. The lang field is the two-character ISO 639-1 code for the language in the required value and description fields. The value field should provide a shorter indication of what information is present in the description field.*

properties (optional): A hash or dictionary of string key/value pairs. This is appropriate for associating application-specific data with the beacon, and is often not human-readable.

Writing metadata records

You may create or modify a record in the system by sending a POST request to a beacon resource specifying its full multipart identifier in the body of the request.

Below is an example of a write request:

curl -X POST -d '{"beacon":{"identifier":"2F234454-CF6D-4A0F-ADF2-F4911BA9FFA6_1_2_ibeacon", "metadata": {"location":{"longitude":38.93,"latitude":-77.22}}}}' -H 'Content-Type: application/json' -H 'Authorization: Token token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE0OTcwMzMxNTJ9.qk0oNd1TWrpQ_1fp4tbO9h4ueIJ2IthHeEaeGLKAYfU"'

Note that the beacon is identified by a its multi-part identifier, and all other writeable information is specified in the metadata section. The location section is required and, must contain at least a valid latitude and longitude.

This example shows only a subset of allowed metadata. An example of a metadata record that includes all fields the latest schema is shown in the previous section.

It is important to note that metadata may be null for records in the system, and typically will be for records imported from WikiBeacon for which no API changes have been made.

Writes to records are rate-limited to prevent vandalism. An audit trail is retained, and users making destructive changes will have access revoked.

Location queries Using metadata

When querying location, it is important to note that there are two different sources of location data: WikiBeacon and Metadata. WikiBeacon locations are imported from automatic detections by the Locate mobile app, with locations based on the reported latitude and longitude known the the phone at the time the beacon was detected. Metadata locations are written to by API users, and are provided to the database with no knowledge of the source of the location information other than the user account used to write the Metadata.

Both sources may be queried. If a metadata location is available it will be used for location queries using the latitude and longitude query fields. (If no metadata location is available it will queries by location will fall back to using the WikiBeacon location, if available.

If you explicitly want to query the WikiBeacon location, you can use the w_latitude and w_longitude query fields.

Accessing history and reverting changes

If you wish to access the history of a record you may do so with a request like below. Note the ?include_history parameter at the end:

 curl -i -XGET -H 'Authorization: Token token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1MDE5NTU1MDR9.oU1Swns1qXa1gKxTveE90ynlq5oozX7Zo2Ex-NAYB4s"'


You can also query a full list of just the changes for a beacon like this:

curl -i -XPOST -d '{"identifier":"2F234454-CF6D-4A0F-ADF2-F4911BA9FFA6_1_2_ibeacon"}' -H 'Authorization: Token token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ3cml0ZWFibGUiOnRydWUsImV4cCI6MTUxODgyNzkzMX0.QyJg5WL0eO-L_JtbWPOFSPfQxkIeCkrxLzVc1UceUuI"'


Authors of a change have permission to revert to their previous change. (Users trying to revert to a history element they did not create will get a 422 access denied.) To revert a change, find the beaconhistory id from the result above, and then issue a revert request like this:

curl -X POST -d '{"beacon_history_id": 1, "reversion_reason":"vandalism"}' -H 'Authorization: Token token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ3cml0ZWFibGUiOnRydWUsImV4cCI6MTUxODgyNzkzMX0.QyJg5WL0eO-L_JtbWPOFSPfQxkIeCkrxLzVc1UceUuI"'


The above will change the beacon values to the ones it had as of the specified beacon_history record. It will insert a new history record that specifies the reversion as having happened, which shows up in the beacon_history query:

curl -X POST -d '{"identifier":"2F234454-CF6D-4A0F-ADF2-F4911BA9FFA6_1_2_ibeacon"}' -H 'Authorization: Token token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ3cml0ZWFibGUiOnRydWUsImV4cCI6MTUxODgyNzkzMX0.QyJg5WL0eO-L_JtbWPOFSPfQxkIeCkrxLzVc1UceUuI"'


Note in the response above, the most recent beacon history specifies "reversion_reason":"vandalism","reversion_beacon_history_id":1

The reversion reason must be one of "vadalism", "mistaken_change" or "incorrect_values"

Creating a new user Via the API

To create a new user programmatically you may call:

 curl -XPOST -H 'Content-Type: application/json' -d '{"user": {"name": "name_d2", "email": "", "password": "abc123"}}'


An confirmation email will be sent to the email address of the user account. If you try to login without confirming the account, you will get an error message like this:

 curl  -XPOST -H 'Content-Type: application/json' -d '{"email":"","password":"abc123"}'

 {"error":"User must first be confirmed by following link in confirmation email"}

The account may be confirmed via the API by providing the proper confirmation token in a call like below:

 curl -XGET -H 'Accept: application/json'


Requesting a password reset, or updating user info

You may reset your password using both the API and the website. To reset it from the website, simply go to, attempt to log in, and then follow the instructions if you get a login failure.

To request a password reset with the API, simply POST the email to the endpoint below:

curl -XPOST -H "Content-Type: application/json" -d '{"email": ""}'


An email will be sent to the requesting address with instructions, which will look like this:

Someone has requested a link to change your password. You can do this with the API using the user id and confirmation token below:

User Id: 1

Reset Password Token: 9e131611c117627eb650460897ad6be9eeaff8d27b927650605498be622bdaff

You can then use the following API to change the password using the token (note the user id from above is at the end of the URL):

curl -XPUT -H "Content-Type: application/json"  -H "Accept: application/json" -d '{"user": { "password": "abcd1234", "reset_password_token": "9e131611c117627eb650460897ad6be9eeaff8d27b927650605498be622bdaff" } }'


Note that if you are authenticated as a user, you may also use this same API to update your password or username without supplying a reset_password_token.

curl -XPUT -H "Content-Type: application/json"  -H "Accept: application/json" -d '{"user": { "name": "my_new_username" } }'  -H 'Authorization: Token token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1MDE5NTU1MDR9.oU1Swns1qXa1gKxTveE90ynlq5oozX7Zo2Ex-NAYB4s"'



If you have been granted a moderator role, you may revert changes of other users. The APIs for doing this are identical to reverting your own changes. See the Accessing History and Reverting Changes section for details.

Moderators may also lock the accounts of users due to abusive behavior. Users with locked accounts will not be able to authenticate to create new tokens or use existing tokens to access beacon records. In order to lock a user's account use the following call:

curl -XPOST -H "Content-Type: application/json"  -H "Accept: application/json" -d '{"id":13,"reason":"Repeat edits appear to be vandalism"}'  -H 'Authorization: Token token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ3cml0ZWFibGUiOnRydWUsImV4cCI6MTUyMjU0NzE4NH0.uEVoc6PqmQ1Jy1At1Y2Gt-cJYBvQdhe055t3HkAnFQ8"'

{"user":{"id":13,"name":"name_d3","email":"","confirmed":true,"moderation_lockout":{"reason":"Repeat edits appear to be vandalism","updated_at":"2018-03-31T01:54:22.002Z"}}}

Similarly, a user may be unlocked with a call like this:

curl -XPOST -H "Content-Type: application/json"  -H "Accept: application/json" -d '{"id":13,"reason":"Repeat edits appear to be vandalism"}'  -H 'Authorization: Token token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ3cml0ZWFibGUiOnRydWUsImV4cCI6MTUyMjU0NzE4NH0.uEVoc6PqmQ1Jy1At1Y2Gt-cJYBvQdhe055t3HkAnFQ8"'


In order to perform either of the above operations, you must know the numeric user id. To get this from the user name, you may call:

curl -H "Accept: application/json" -H 'Authorization: Token token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ3cml0ZWFibGUiOnRydWUsImV4cCI6MTUyMjU0NzE4NH0.uEVoc6PqmQ1Jy1At1Y2Gt-cJYBvQdhe055t3HkAnFQ8"'


Pattern Locks

The system supports locking beacon identifier patterns so that only those who own the identifier patterns may make changes to beacons matching those patterns. The each pattern is specific to a beacon format and identifier prefix. For example, one user might be granted ownership for all beacons with the iBeacon format starting with the first identifier of 2F234454-CF6D-4A0F-ADF2-F4911BA9FFA6.

When such an ownership is set up, it is called a "pattern lock", and it means that only the owning user (or authorized delegate users) may make changes to beacons matching this identifier pattern. A pattern lock may only be put in place by a moderator (or administrator) when warranted. An example that might warrant setting up a pattern lock is if one or more users repeatedly make unwanted changes to metadata for beacons that the owning user can demonstrate are controlled by his or her organization.

Creating a pattern lock:

If you have a moderator role, you can create a new pattern lock as follows. (If you do not have a moderator role, you may send an email to request that a pattern lock be created for beacons you own.)

curl -i -XPOST -H 'Content-Type: application/json' -H 'Authorization: Token token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ3cml0ZWFibGUiOnRydWUsImV4cCI6MTUyMzg5MDIwN30.D32NAWTlif8_vzuX9UMXdobgbv3Pcr8t2KAV-JXD5gs"' -d '{"pattern_lock": {"identifier_prefix":"00000000-0000-0000-0000-000000000000", "beacon_type": "ibeacon", "owner_user_name": "david"}}'

Once a pattern lock is created, any attempt to modify a beacon record in this system that matches the pattern lock by a user that is not authorized (not the owner, a delegated user, or a moderator) will receive a 401 Unauthorized error.

Querying pattern locks

Anyone may find out what pattern locks are active for an identifier prefix by doing a pattern lock query. The response will tell you all pattern locks that exist for any beacon identifier starting with the supplied prefix, the user who owns the pattern lock, and the user (moderator) who created the pattern lock.

curl -i -XPOST -H 'Content-Type: application/json' -H 'Authorization: Token token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ3cml0ZWFibGUiOnRydWUsImV4cCI6MTUyMzg5MDIwN30.D32NAWTlif8_vzuX9UMXdobgbv3Pcr8t2KAV-JXD5gs"' -d '{"identifier_prefix": "00000000-0000-0000-0000-000000000000"}'


Adding a user to a pattern lock:

If you are the owner of a pattern lock, you may delegate other users to make changes for the beacon pattern. This is useful to give write access to other users you trust (either in your organization or outside of it) write access to beacon data.\

You must supply the numeric identifier of the pattern lock (obtainable by the query method above) to add users to it.

curl -i -XPOST -H 'Content-Type: application/json: Token token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ3cml0ZWFibGUiOnRydWUsImV4cCI6MTUyMzg5MDIwN30.D32NAWTlif8_vzuX9UMXdobgbv3Pcr8t2KAV-JXD5gs"' -d '{"user_name": "davidgyoung"}'


When you grant a pattern lock to a user, that user will automatically be sent an email at their registered email address indicating that you have granted them access to the pattern lock.

Deleting a pattern lock you own

curl -i -XDELETE -H 'Authorization: Token token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ3cml0ZWFibGUiOnRydWUsImV4cCI6MTUyNDUwNTUxOX0.Ajs8fPmAd8gjgxbvzw88hxuqmYWwufxgHMsqZ-v8kPE"'

HTTP/1.1 204 No Content

Requesting access to a pattern lock

If you get a 401 Unauthorized error trying to write to a beacon that is covered under a pattern lock, you may request to be added as a delegated user of the pattern lock. This will send an email to the registered email address of the owner and include the message provided in the request. This email will not include your email address or any identifying information other than your Ningo user name, so it is a good idea to provide contact info in the message. Because this API does nothing more than send an email to the owner requesting access to the pattern lock, there is no guarantee that you will be granted access or be contacted by the pattern lock owner.

curl -i -XPOST -H 'Content-Type: application/json' -H 'Authorization: Token token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ3cml0ZWFibGUiOnRydWUsImV4cCI6MTUyNDI2MjM1NX0.UVNED2Wvf-1mbdlpeNKL_ta-ofvmGI2G0WnqK-a7v5c"' -d '{"message": "My name is David Young and I am a beacon researcher who would like access to update placement details for these beacons.  Please contact me at if you have any questions."}'

{"status":"email sent"}

Need Help?

Send an email to if any of the steps above don't work for you.