Get user's address

This is a quick tutorial on how to get a user's address. Its split into two steps: authentication, and requesting the address. Make sure you have an API Key before you start.

STEP 1: Authentication

Use the OAuth flow to get the user's permission to read an address gem. First, make the authentication call to read the Address gem (make sure to add your API Key).

GET https://api-sandbox.personal.com/oauth/authorize?client_id=<API Key>
          &response_type=code
          &redirect_uri=https://www.sandbox.personal.com
          &scope=read_0037
          &update=false

The user will be presented with a pop-up that asks them to log in, and choose which of their existing addresses to let you have access to. If the user is already logged into Personal, they will not have to log in again, but they will still have to choose which addresses to let you have access to.

Personal Connect: Address

After the user gives the app permission to some addresses, the user will be automatically redirected to the callback URL provided in the call above (https://www.sandbox.personal.com/), and a code will be appended to the end.

https://www.sandbox.personal.com/callback?code=<code>

Use the code to request the access token (make sure to add your API Key and Shared Secret). Note that the redirect URL must be the same as the one provided in the authorization request, and the POST body must be URL encoded. 

POST : https://api-sandbox.personal.com/oauth/access_token
            Content-Type: application/x-www-form-urlencoded;charset=UTF-8

            <post body>
            grant_type=authorization_code&
            code=<code>&
            client_id=<API Key>&
            client_secret=<Shared Secret>&
            redirect_uri=https://www.sandbox.personal.com

You will recieve a response that contains the access token along with the time in seconds that the token is valid for.

HTTP/1.1 200 OK     
            Content-Type: application/json;charset=UTF-8
            Cache-Control: no-store
            Pragma: no-cache      

            {   
              "access_token": "2YotnFZFEjr1zCsicMWpAA",
              "token_type": "example",   
              "expires_in": 3600, 
              "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",   

              "#": "This variable specifies how often the client should resynchronize data",   
              "gem_refresh_interval": "<timeinseconds>"
            }

 

 

STEP 2: Request address

Now that you have the access token with permission to read the gem, you need to get the actual data. And you will need to do this before the access token expires (see the OAuth2 Authentication documentation on how to get a refress token).

First you should request the gem id (and be sure to use your API Key and the access token you got from step 1.

GET : https://api-sandbox.personal.com/api/v1/gems/?client_id=<API Key>
          Authorization: Bearer <access_token>

Your response will be in the following format. The number of items in the responce will depend on how many gems the user has in their vault and how many they have given you access to. You need the gem instance id for a gem to proceed. Note that there must be at least one gem that you ahve permission to for this call to succeed.

          {
            "gems": [
            {
              "gem_instance_id": "ffffffff",
              "gem_instance_name": "My test gem",
              "gem_template_id": "0000",
              "gem_type": "my",
              "created_timestamp": 12353465,
              "updated_timestamp": 234656456,
              "access_permissions": [
                "read",
                "write",
                "create"
              ],
              "creation_type": "<implicit/user>"
            },

            {
              "#": "If there are no instances of this gem template",

              "gem_template_id": "0003",
              "gem_type": "my",
              "access_permissions": [
                "create"
              ]
            }
            ] 
          } 

Now use the gem instance ID to read the actual address (and include your API Key and bearer token).

GET : https://api-sandbox.personal.com/api/v1/gems/<fffffffff>?client_id=<API key>
          Authorization: Bearer <access_token>      
          Secure-Password: <password>                  (this is custom HTTP header) 

The response will be the data for the address gem you requested.

          {
            "gem": {
              "info": {
                "gem_instance_id": "ffffffff<…>",
                "gem_instance_name": "My test gem",
                "gem_template_id": "0037",
                "gem_type": "my",
                "created_timestamp": 12353465,
                "updated_timestamp": 234656456,
                "creation_type": "<implicit/user>"
              },
              "data": {
                "string_field": "data1",
                "integer_field": 12,
                "string_multi": [
                  "string1",
                  "string2",
                  "string3"
                ],
                "complex_multi": [
                {
                  "company": "mycompany",
                  "position": "tester",
                  "other_field": "someotherdata"
                },
                {
                  "company": "othercompany",
                  "position": "someotherposition"
                }
                ],
                "image_file": "<image/fileid>"
              },

              "attachments": {
                "1234": {
                "id": "1234",
                "ext": "doc"
              },
              "2345": {
                "id": "2345",
                "ext": "jpg"
              }
            }

            "#": "Access is only valid for 'my gems'",

            "access": {
              "owners": [
                {
                  "id": "d41b3d2f-fe15-4f73-a161-c8755847096a",
                  "firstname": "John",
                  "lastname": "Smith",
                  "email": "john@personal.com",
                  "phone": "1234567890",
                  "username": "johns",
                  "contact_avatar": "https: //…<pathtoavatar>"
                }
              ]
            }
          }
        }

Libraries


Ruby Library

Install

Manual Install:
gem install personal_api_client
Gemfile:
gem "personal_api_client", "~> 0.0.1"
Gemfile to stay bleeding edge (not recommended):
gem "personal_api_client", :git => "git://github.com/Personal/ruby-api-client.git"

Use

OAuth flow

  1. Initialize Personal OAuth2 Client
    parameters = {
        :client_id => <your_client_id>,
        :client_secret => <your_client_secret>,
        :target_site => <api_endpoint - e.g., https://api-sandbox.personal.com>,
        :callback_uri => <redirect_uri - e.g., https://myhost/oauth/callback>,
        :scope => <scope - e.g., read_0135>
    }
    client = Oauth2Client.initialize_auth_code(parameters)
    
    For reference on defining scope, see Authorization Code Flow
  2. Redirect to Authorization URL
    redirect_to client.authorize_url
    
  3. Authorization code will arrive to the callback URL you specified in :callback_uri. Get access token.
    parameters = {:code => params[:code], :callback_uri => <redirect_uri from previous_request>}
    access_token = client.get_access_token(parameters)
    

API interaction

  1. Initialize Personal API Client
    personal_api_client = PersonalApiClient.new(<access_token>, <your_client_id>)
    
  2. Call methods to perform API operations. For reference in building request body, consult API Reference Docs

Add'l links

Other

Node.js, iOS and Android SDKs coming soon. To contribute, fork a project on GitHub or contact us.

Authorization code flow

The OAuth2 Authorization Code Flow provides the developer a way to request access to user resources so the developer can access them if the user gives permission. This consists of three steps:

  1. User is redirected to Personal's authorization UI where they logs in and give the app permission to resources.
  2. User is redirected to developer URL (callback URI) with authorization code appended
  3. Developer uses 'code' to get access token

Implemented per https://tools.ietf.org/html/draft-ietf-oauth-v2-25#section-4.1

 

Step 1: Authorization request (redirect user to the following URL)

GET https://<host>/oauth/authorize?client_id=<id>
  &response_type=code
  &redirect_uri=<redirect URI>
  &scope=<resources to request>
  &update=<true/false>

Parameters:

  • 'client_id' - the API Key you were given
  • response_type’ - must be set to 'code' per OAuth2
  • redirect_uri’ - the 3rd party implemented callback where the user is redirected once the authentication is complete. This callback is passed the ‘code’ per OAuth2 specification.
  • scope’ - specifies requested resource (see the table below)
  • 'update' - specifies if the selection UI dialog should be presented even if the 3rd party already has access to the requested resource. This dialog allows users to change their current permissions. If the value is set to ‘false’, only authentication is performed (if needed) and 3rd party is provided with the access token and the below specified response.

 

The list of resources that can be requested:

Resource

Permissions

Examples

Gems

read/write/create/grant

Syntax:

scope='permission'_<template id>

scope=read_0000

scope=write_0001

scope=create_0002

scope=grant_0003

scope=read_0001,write_0001

Request gems on user's behalf

read_access (true/false)

 

scope=read_access

Contacts read/write

read_contacts/write_contacts

 

scope=read_contacts

scope=write_contacts

Messages read/write

read_messages/write_messages

scope=read_messages

scope=write_messages

Notes:

For the complete a list of <template id>'s and a description of what each does, use the schema calls.

Once you have the permission to do something, you can actually make those requests. Some permissions are implied:

  • Read: developers can read gem instances if you have 'read' permissions for that gem instance
  • Write: developers can write to gem instances if you have 'write' permissions to that gem instance. Write permission implies 'read' permission.
  • Create: developers can create new instances of a gem if you have the 'create' permission on that gem template. You automatically get read and write permission for any gem instance you have created.
  • Grant: developers can grant access (share) to gem instances on user behalf if you have 'grant' permission on that gem instance.

Step 2: Sample callback (grab the appended code)

User is redirected to callback URL provided by the 3rd party in previous requests. For example:

https://www.3rdparty.com/callback?code=<code>

Step 3: Access token request (use code to get access token)

The developer issues the following request in order to get the access token.

POST : https://<host>/oauth/access_token
Content-Type: application/x-www-form-urlencoded;charset=UTF-8

<post body>
 grant_type=authorization_code&
 code=<code>&
 client_id=<client id>&
 client_secret=<client secret provided during API approval>&
 redirect_uri=<redirect URI>

redirect_uri - must be the same as provided in authorization request

 

The response should look like:

HTTP/1.1 200 OK     
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache      

{   
  "access_token": "2YotnFZFEjr1zCsicMWpAA",
  "token_type": "example",   
  "expires_in": 3600, 
  "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",   

  "#": "This variable specifies how often the client should resynchronize data",   
  "gem_refresh_interval": "<timeinseconds>"
}

Note: POST body must be URL encoded. Please make sure that you escape appropriate characters otherwise authentication will fail.

The response above gives you the access token, expiration for the access token (in seconds), and the refresh token. To get a new access token once the access token has expired, just change the step 3 request "grant_type" to "refresh_token" like below, and pass the refresh token instead of the access token. You will get a new refresh token to store. There is more info at https://tools.ietf.org/html/draft-ietf-oauth-v2-21#section-6 :

POST : https://<host>/oauth/access_token
Content-Type: application/x-www-form-urlencoded;charset=UTF-8

  <post body>
  grant_type=refresh_token&
  refresh_token=<refresh token>&
  client_id=<client id>&
  client_secret=<client secret provided during API approval>

Client credentials flow

The Client Credentials Flow provides direct developer authentication so that the developer can access non-user specific data from Personal including:

  • Gem Schema Operations
  • Avatar Image Operations
  • Community Gem Operations

Impemented per https://tools.ietf.org/html/draft-ietf-oauth-v2-25#section-4.3.

 

Request:

POST : https://<host>/oauth/access_token
Content-Type: application/x-www-form-urlencoded;charset=UTF-8

<post body>
 grant_type=client_credentials&
 client_id=<API key>&
 client_secret=<Shared secret>

Response (JSON):

HTTP/1.1 200 OK
Content-Type: application/json;chartset=UTF-8
Cache-Control: no-store
Pragma: no-cache


  {
"access_token": "0t9k7b13f8v5p7sbn9pf",
"refresh_token": "nor069fa5jz9g5qwuko5",
"expires_in": 3600,
"token_type": "bearer",
"gem_refresh_interval": "600"
}

IMPORTANT NOTE: Your Secure Password can be either changed or reset.

  • Changing the Secure Password will let you keep all the sensitive data granted to you by users so far
  • Resetting the Secure Password will remove your access to all sensitive data granted you by users so far. In oder to access sensitive data again, you will have to promt users for access permissions again.

In order to change or reset secured password, 'Client Authentication' needs to be performed first and an access token needs to be obtained.

Changing Secure password request:

POST : https://<host>/api/v1/client_settings/change_secure_password
          Authorization: Bearer <token>
          Content-Type: application/json

          {
            "old_password": "<old password>",
            "new_password": "<new password>"
          }

Resetting Secure password request:

POST : https://<host>/api/v1/client_settings/reset_secure_password
          Authorization: Bearer <token>
          Content-Type: application/json

          {
            "new_password": "<new password>"
          }
Gem Schema Reference

A reference of all available gem templates and their fields

Error Code Reference

A reference of all the possible error codes and return JSON

Gem schema


Place holder for gem schema tool.

Error codes

These are generic HTTP error codes that can be returned. Each error message also returns JSON with additional information what went wrong.

  • 400 Bad request - Request format is not valid.
  • 403 Forbidden - Client does not have access to this resource.
  • 404 Resource not found - Specified resource cannot be found.
  • 409 Conflict - There is a data conflict when trying to perform the API request. JSON code specifies details.

Please note that some of the requests return 200 OK status with error code in order to report the errors.

The format of detailed error message (JSON) is:

{
  "error": "<error code>",
  "error_description": "<displayable error description>"
}

 

File-related error codes

# USER

ExceptionUserNotAuthenticated
'User Not Authenticated'
ExceptionUserPasswordRequired
'User Password Required For This Request'
ExceptionUserNotFound
'User Not Found'
ExceptionUserHasNoFiles
'User Has No Files'
ExceptionUserFileLimitReached
'Your file cannot be uploaded. You have reached the <storage_limit> MB storage limit.'

 

# FILE

ExceptionFileTooBig
'Oops, your file exceeds the <single_file_size_limit> MB limit on individual file uploads.'
ExceptionFileNotUploaded
'File could not be uploaded.  Please try again.'
ExceptionFileNotFound
'File Not Found'
ExceptionFileDoesNotBelongToYou
'Requested File Does Not Belong To You'
ExceptionFileAlreadyLinked
'Requested File Is Already Linked To Profile'
ExceptionFileUnauthorizedAccess
'You Are Not Authorized To Access This File'
ExceptionFileThumbnailSizeNotAllowed
'Requested Thumbnail Size Is Not Allowed'

 

# PROFILE

ExceptionProfileNotFound
'Profile Not Found'
ExceptionProfileDoesNotBelongToYou
'Profile Does Not Belong To You'

 

# THIRD PARTY STORAGE (TPS)

ExceptionThirdpartyNotSignedIn
'You Have Not Logged In With Requested Third-party Service'
ExceptionThirdpartyTokenCorrupt
'Third-party Token Corrupt'
ExceptionThirdpartyDisabled
'Third-party is disabled'
ExceptionThirdpartyServiceUnsupported
'Unsupported third-party service'
  

This section describes the gem operations.


 Note To request gems with sensitive fields, you must also pass the Secure Password in the call (as specified in the call). By default, the Secure Password is your Shared Secret. You should change the Secure Password so that you are the only one who knows it.

GET /gems

Gets a list of all gem instances the user has given your app access to.

Request:

GET : https://<host>/api/v1/gems[/<filter>]?client_id=<Personal API key>
Authorization: Bearer <access_token>

<filter> is optional. If missing, the call defaults to ‘all gems’. You can filter by:

  • ‘my’ – List of my gems
  • ‘others’ – List of gems from others

Response (JSON):


          {
            "{
    "gems": [
        {
            "gem_instance_id": "ffffffff…",
            "gem_instance_name": "My test gem",
            "gem_template_id": "0000",
            "gem_type": "my",
            "created_timestamp": 12353465,
            "updated_timestamp": 234656456,
            "access_permissions": [
                "read",
                "write",
                "create"
            ],
            "creation_type": "<implicit/user>"
        },
        {
            "gem_instance_id": "efffffff<…>",
            "gem_instance_name": "Test gem from others",
            "gem_template_id": "0001",
            "gem_type": "others",
            "create_timestamp": 12353465,
            "updated_timestamp": 234656456,
            "access_permissions": [
                "read"
            ],

            "#": "If gem_type==others",

            "allowadopt": "<true/false>",
            "owner": {
                "username": "johns",
                "contact_avatar": "https: //…<pathtoavatar>"
            }
        },
        {
            "#": "If there are no instances of this gem template",

            "gem_template_id": "0003",
            "gem_type": "my",
            "access_permissions": [
                "create"
            ]
        }
    ]
} 

Examples:

https://<host>/api/v1/gems

https://<host>/api/v1/gems/my

https://<host>/api/v1/gems/others

 

Error responses/code (using standard error format)

400 Bad Request

Error codes:

  • "invalid_request" - Misformated autheorication request
  • "invalid_client" - Client failed authentication
  • "unauthorized_client" - Client is not authorized to use this grant type
  • "unsupported_grant_type" - Specified grant type is not supported

 

 

GET /gems/{gem_instance_id}


Gets the gem instance data for specified gem instance id. Post parameter ‘Secure-Password’ is required for any gems with sensitive data (denoted by the lock next to the field in the web or mobile product). If the 'Secure-Password' is not included, the sensitive data will not be returned. It is also possible to get the gem schema with the gem by adding query string paramater "expand=schema".

Example 1

Request (for both my gems and gems from others):

GET : https://<host>/api/v1/gems/<gem_instance_id>?client_id=<Personal API key>
Authorization: Bearer <access_token>      
Secure-Password: <password>                  (this is custom HTTP header) 

Response (JSON):

  "{
    "gem": {
        "info": {
            "gem_instance_id": "ffffffff<…>",
            "gem_instance_name": "My test gem",
            "gem_template_id": "0000",
            "gem_type": "my",
            "created_timestamp": 12353465,
            "updated_timestamp": 234656456,
            "creation_type": "<implicit/user>"
        },
        "data": {
            "string_field": "data1",
            "integer_field": 12,
            "string_multi": [
                "string1",
                "string2",
                "string3"
            ],
            "complex_multi": [
                {
                    "company": "mycompany",
                    "position": "tester",
                    "other_field": "someotherdata"
                },
                {
                    "company": "othercompany",
                    "position": "someotherposition"
                }
            ],
            "image_file": "<image/fileid>"
        },

  "attachments": {
    "1337beef-7e57-4282-8b91-48a0cb75fd74": {
      "id": "1337beef-7e57-4282-8b91-48a0cb75fd74",
      "user_id": "2047da6b-b831-3727-ff37-dead1375fd74",
      "name": "file1.doc",
      "mime-type": "application/msword",
      "size": "7069",
      "md5": "3d9bcc6e714d0402c96a83324f8e0f92",
      "url_file": "https://www.personal.com/file/1337beef-7e57-4282-8b91-48a0cb75fd74"
    },
    "028fb572-1a7c-1037-64df-662ecb987f2d": {
      "id": "028fb572-1a7c-1037-64df-662ecb987f2d",
      "user_id": "9836cc3f-b347-134d-fe47-352f4d885c5a",
      "name": "file2.png",
      "mime-type": "image/png",
      "size": "3948",
      "md5": "9d6f5b5389860990da2180f0c4dbeac7",
      "url_file": "https://www.personal.com/file028fb572-1a7c-1037-64df-662ecb987f2d"
    }
   },

        "#": "Access is only valid for 'my gems'",

         "access": {
            "owners": [
                {
                    "id": "d41b3d2f-fe15-4f73-a161-c8755847096a",
                    "firstname": "John",
                    "lastname": "Smith",
                    "email": "john@personal.com",
                    "phone": "1234567890",
                    "username": "johns",
                    "contact_avatar": "https: //…<pathtoavatar>"
                }
            ]
        }
    }
}"

Example 2

Request (same as above, but also including schema):

GET : https://<host>/api/v1/gems/<gem_instance_id>?client_id=<Personal API key>&expand=schema
Authorization: Bearer <access_token>      
Secure-Password: <password>                  (this is custom HTTP header) 

Response (JSON):

  " {
    "gem": {
    "info": {
      "gem_instance_id": "86332986-01a5-4544-a88f-5a7e86c789b8#0000#7d2fd3ad-3850-4046-a6bc-59a57bb15e0d",
      "gem_instance_name": "name",
      "gem_template_id": "0000",
      "created_timestamp": "1352827803418",
      "updated_timestamp": "1352827804691",
      "creation_type": "user"
    },
    "data": {
      "_template_id": "0000",
      "_template_name": "Name",
      "_template_category": "0000",
      "_groups": {
        "The Essentials": {
          "name": "The Essentials",
          "id": "about_basics",
          "index": "01",
          "text": "The Essentials",
          "fields": [
            "# All fields"
          ],
          "parent_profile": "0000"
        },
        "#": "Other groups ..."
      },
      "_fields": {
        "my_gem_name": {
          "family": "data",
          "column": "my_gem_name",
          "display_name": "Gem Name",
          "description": "This gem will be saved as this name.",
          "minable": "false",
          "index": "01",
          "instance_name": "true",
          "complex": "false",
          "multivalue": "false",
          "sensitive": "false",
          "track_values": "false",
          "suggest_tracked": "true",
          "parent_profile": "0000",
          "validation": {
            "type": "STRING",
            "opt_fields": {
              "not_empty": true,
              "not_null": true,
              "max": "4096",
              "sort": "true",
              "validate": true
            }
          },
          "hint": {
            "control": {
              "autocomplete": "false",
              "name": "textbox",
              "other_label": "Other"
            }
          },
          "tag_source": "false"
        },
        "#": "All other fields"
      },
      "#": "Remaining properties are the same as Example 1",
    },
    "attachments": {
      "#": "Same as Example 1"
    },
    "access": {
      "#": "Same as Example 1"
    }
  }
}"

PUT /gems/{gem_instance_id}

Write to existing gem. Values specified in the JSON are saved in the database. Values NOT specified in the JSON that already exist in database will be deleted.

Resource:

PUT : https://<host>/api/v1/gems/<gem_instance_id>?client_id=<Personal API key>
Authorization: Bearer <access_token>      
Secure-Password: <password>      (this is custom HTTP header)

 

Request body (JSON):

  " {
    "gem": {
        "info": {
            "gem_instance_id": "ffffffff<…>",
            "gem_instance_name": "My test gem",
            "gem_template_id": "0000",

            "#": "See the note below about updated_timestamp",
            "updated_timestamp": 234656456
        },
        "data": {
            "#": "Same format as in GET request"
        }
    }
}"

Note about "updated_timestamp":

‘updated_timestamp’ has the special meaning here. Timestamp that was returned during last GET request should be sent here. Server will use this in order to detect if the gem changed on the backend since the last time it was retrieved. If gem changed, PUT request will fail and client will have to retrieve new version of the gem before making updates.

Reponse:

Success/Failure + JSON


POST /gems


Creates a new gem.

Resource

POST : https://<host>/api/v1/gems?client_id=<Personal API key>
Authorization: Bearer <access_token>      
Secure-Password: <password>            (this is custom HTTP header)

Request body (JSON):

{
  {
    "gem": {
        "info": {
            "gem_instance_name": "My test gem",
            "gem_template_id": "0000",

            "#": "If this gem is imported/adopted",
            "adopted": true,
            "adopted_gem_id": "<gem id>"
        },

        "data": {
      "my_gem_name": <name_of_gem_instance>
            "#": "Same format as in GET request"
        }
    }
}
}

 

Response (JSON):

{
  {
    "gem": {
        "info": {
            "gem_instance_id": "ffffffff<…>",
            "gem_instance_name": "My test gem",
            "gem_template_id": "0000",
            "gem_type": "my",
            "create_timestamp": 12353465,
            "updated_timestamp": 234656456
        }
    }
}
}

DELETE /gems/{gem_instance_id}

Deletes existing gem.

Resource:

DELETE : https://<host>/api/v1/gems/<gem_instance_id>?client_id=<Personal API key>
Authorization: Bearer <access_token>      

Response:

Success/Failure + JSON


POST /file


Use this method to upload a file to a gem. All files must be attached to a gem instance so make sure you have access to edit a gem. Make sure to use the gem instance id for the gem the file needs to be attached to.

Request:

POST : https://<host>/file?files[]=<filename>&gem_id=<gem_instance_id>&client_id=<Personal API key>
Authorization: Bearer <access_token>
Secure-Password: <password>
Content-type: application/octet-stream
Content-Length: <File Byte Count>
<attached file>

Response (JSON):

 

{
    "success": true,
    "id": "cfdabf9b-1acc-458b-b3f0-297888e6c17d",
    "user_id": "c0111ebd-9746-46ac-b5e4-fc34d688e5da",
    "name": "<escaped file name - see note below>",
    "original_file_name": "<original/unescaped file name - see note below>",
    "mime-type": "image/jpeg",
    "type": "IMAGE",
    "size": 678266,
    "md5": "a279a3e100bbfd5996bbbcfcf14d11ef",
    "url_file": "https://<host>/file/cfdabf9b-1acc-458b-b3f0-297888e6c17d",
    "gem_id": "c0111ebd-9746-46ac-b5e4-fc34d688e5da#0174#f4ccd229-0012-4047-aa0d-ac94db5f35a1",
    "third_party_service": "",
    "updated": 1344603146853,
    "url_image_120": "https://<host>/file/cfdabf9b-1acc-458b-b3f0-297888e6c17d?size=120",
    "url_image_100": "https://<host>/file/cfdabf9b-1acc-458b-b3f0-297888e6c17d?size=100",
    "url_image_75": "https://<host>/file/cfdabf9b-1acc-458b-b3f0-297888e6c17d?size=75",
    "url_image_50": "https://<host>/file/cfdabf9b-1acc-458b-b3f0-297888e6c17d?size=50",
    "url_image_30": "https://<host>/file/cfdabf9b-1acc-458b-b3f0-297888e6c17d?size=30",
    "url_image_24": "https://<host>/file/cfdabf9b-1acc-458b-b3f0-297888e6c17d?size=24"
}

Note about file name(s):

Once the file is uploaded, its name is changed (escaped) using the following rule. Characters \  /  : * ? " < > | ' are replaced with _ . This is in order to prevent possible XSS attacks by embedding special characters into file name and interfering with how Personal portal displays these names. Escaped (chaned) file name is provided in the "name" parameter. 

For reference purposes, original (unescaped) name is returned in "original_file_name". Application using API can use this value if needed. However, application developers should be careful in using this due above mentioned risk of XSS attacks.


GET /file

To get a file from the Personal File Service:

GET : https://<host>/file/<file id>?[size=<24,30,50,75,100,120>&]client_id=<Personal API key>
Authorization: Bearer <access_token>
Secure-Password: <password> 

Note: If the 'size' parameter is specified, file thumbnail of the specified size is returned.


DELETE /file

Delete a file from a gem:

DELETE : https://<host>/file/<file id>?client_id=<Personal API key>
Authorization: Bearer <access_token>
Secure-Password: <password> 

Deleting a file automatically removes it from the gem it was attached to.


POST /access/grant

Grants the specified list of people access to the specified list of gem instances (with any attached files). Also refered to as sharing gem instances. You must have permission to grant or share the gem instance(es) on behalf of the user.

POST : https://<host>/api/v1/access/grant?client_id=<Personal API key>
Authorization: Bearer <access_token>
Secure-Password: <password> 

Request body (JSON):

{
    "gems": [
        "<gem_instance_1>",
        "<gem_instance_2>"
    ],

    "#": "#Owners can be referenced by email, id or user name",

     "owners": [
        {
            "type": "email",
            "value": "<E-mail_address>"
        },
        {
            "type": "id",
            "value": "<User_id>"
        },
        {
            "type": "username",
            "value": "<Username>"
        }
    ],

    "message": "<custom message to user>",
    "allowadopt": true
}

Response:

Success/Failure + JSON


POST /access/request

Requests access from the specified list of people to the specified gem template. You must have permission to request gem templates on behalf of the user.

Request:

POST : https://<host>/api/v1/access/request?client_id=<Personal API key>
Authorization: Bearer <access_token>

Request body (JSON):

{
    "templates": [
        "<gem_template_1>",
        "<gem_template_2>"
    ],

    "owners": [
        {
            "type": "email",
            "value": "<E-mail address>"
        },
        {
            "type": "id",
            "value": "<User id>"
        },
        {
            "type": "username",
            "value": "<Username>"
        }
    ],

    "message": "<custom message to user>"
}

Response:

Success/Failure + JSON


POST /access/email

E-mails the specified e-mail address(es) the specified gem instances. You must have permission to grant or share the gem instance(es) on behalf of the user.

Request:

POST : https://<host>/api/v1/access/email?client_id=<Personal API key>
Authorization: Bearer <access_token>

Request body (JSON):

  {
    "gems": [
        "<gem_instance_1>",
        "<gem_instance_2>"
    ],

    "owners": [
        {
            "type": "email",
            "value": "<E-mail address>"
        }
    ],

    "message": "<custom message to user>"
}

Response:

Success/Failure + JSON

 GET



/api/v1/gems/<gem_instance_id>/tags

Guidance on how to query tags attached to a Gem instance

 POST



/api/v1/gems/<gem_instance_id>/tags

Guidance on how to attach tags to a Gem instance

 DELETE



/api/v1/gems/<gem_instance_id>/tags

Guidance on how to remove tags from a Gem instance


GET /gems/<gem>/tags

GET: https://<host>/api/v1/gems/<gem_id>/tags?client_id=<client_id>
Authorization: Bearer <access_token>

 

Example response :

{
  "tag": [
    "me", "my", "car"
  ]
}

 

Response if gem is new and has never had tags:

{}


 



POST /gems/<gem>/tags

POST: https://<host>/api/v1/gems/<gem_id>/tags?client_id=<client_id>
Authorization: Bearer <access_token>

Example request body (JSON):

{
  "tag": [
    "car", "vehicle"
  ]
}

 

Response code: 200 

Response body (JSON):

{
  "result": "success"
}

 

Response code: 403

Response body (JSON):

{
  "type": "error",
  "message": "Unauthorized access!",
  "details": "389src4eqnxrq9mmuwwnbc37 haven't got required level of access to gem 2e2db3f6-6b63-47cb-8bb1-0b5f8ba3acd0"
}

DELETE /gems/<gem>/tags

DELETE : https://<host>/api/v1/gems/<gem_instance_id>/tags?client_id=<Personal API key>
Authorization: Bearer <access_token>      

 

Example request body (JSON):

{
  "tag": [
    "car"
  ]
}

 

Response (JSON):

{
  "result": "success"
}

This section describes the gem operations.

  • GET /schema - Retrieve the full gem data schema (including gem template name, description, category, fields, field type and more)
  • GET /schema/version - Retrieve the gem data schema version number
  • GET /source - Retrieve list of all sources not included in the schema (due to size)
  • GET /source/<source> - Retrieve specific source values
  • POST /validate - Validate fields

We also show you:

  • Field types

GET /schema

Gets the gem schema.You can use this schema to generate dynamic input/output forms. Note that some fields have validated lists of values that are too large to include here so they are in the /GET source call.

Resource:

GET : https://<host>/api/v1/schema[/<gem_template_id>]?client_id=<Personal API key>
Authorization: Bearer <access_token>

<gem_template_id> is optional. If missing this call defaults to all. You can filter by any of the gem template ids.

 

Response (JSON):

[
    {
        "template": {
            "template_id": "0000",
            "template_name": "My Basic Info",
            "template_description": "Description of this gem",
            "template_category": "Basics",
            "template_sensitive": "<true/false>",
            "template_added": "<true/false>",
            "template_icon": "https: //…<pathtoicon",
            "template_multivalue": "<true/false>",
            "related": [
                "<template_id1>",
                "<template_id2>"
            ]
        },
        "fields": [
            {
                "field_id": "<fieldid>",
                "field_name": "<fieldsname>",
                "field_description": "<fielddescription>",
                "field_type": "<type>",
                "control_type": "<control_type>",
                "grouping": "<groupingname>",
                "sensitive": "<true/false>",
                "multivalue": "<true/false>",
                "autocomplete": "<true/false>",
                "required": "<true/false>",
                "control_options": {
                    "source": "<sourcename>",
                    "values": [
                        "<value1>",
                        ""
                    ],
                    "mask": "<mask used for string>",
                    "min": "<min value used for integers>",
                    "max": "<max value used for integers>"
                },

                "#": "For COMPLEX type only",
                "complex_multi": "<true/false>",
                "complex_data": {
                    "#": "Any number of simple fields"
                }
            }
        ]
    }
]

Note: ‘mask’ formats are as follow.

There are 3 reserved characters to identify data format: '9' (for 0-9), 'a' (for a-z, A-Z], '*' (for 0-9, a-z, A-Z). All other characters should be rendered on the form but not passed as 'data'

For example:

  • Schema: (999)999-9999, Display on the form: (___)___-____, Data that is passed to us as 'data': <10 digit number only> 
  • Schema: 999-99-9999, Display on the form: ___-__-____, Data that is passed to us as 'data': <9 digit number> 
  • Schema: (aa) xxx (aa), Display on the form: (__) xxx (__), Data that is passed to us ad 'data': <4 characters>

GET /schema/version

Retrieves current version of the Gem data schema. The entire schema is quite big and does not change very often. Clients should use this call to check if the version has changed to know whether to retrieve the new one.

Resource:

GET : https://<host>/api/v1/schema/version?client_id=<Personal API key>
Authorization: Bearer <access_token>            

Response (JSON):

  {
    "schema": {
        "version": "<schemaversion>"
    }
}

GET /source

Retrieve the list of sources for fields in the Gem data schema. Note that this is due to the fact that some fields have validated lists of values that are too large to include in the schema. Each field in the schema is either be tagged "value" or "source".

Request:

GET : https://<host>/api/v1/source?client_id=<Personal API key>
Authorization: Bearer <access_token>      

Returns (JSON):

 

[
    {
        "source": "<sourcename>",
        "updated_timestamp": 12312763
    }
]

GET /source/{source}

Retrieves the values in a particular source. To avoid downloading this resource when not needed, check ‘updated_timestamp’.

Request:

GET : https://<host>/api/v1/source/<source>?client_id=<Personal API key>
Authorization: Bearer <access_token>      

Returns (JSON):

  {
    "<source name>": [
        "<value1>",
        "<values2>"
    ]
}

POST /validate

Validate data for specified fields.

Request:

POST : https://<host>/api/v1/validate?client_id=<Personal API key>
Authorization: Bearer <access_token>

Request body (JSON):

{
    "data": {
        "field1": "data1",
        "field2": "data2"
    }
}

Response: Success (200 OK) / Failure (409 Conflict). In case of failure the following JSON is returned:

{
    "data": {
        "#": "Only fields that failed validation are returned here",
        "field2": {
            "status": "invalid",
            "reason": "example: must be one of(1, 2, 3)"
        }
    }
}

Field Types

Field type

Control type

Control options

Note

STRING

textbox

textarea

source

values

For strings, ‘source’ may or may not be present. Source specifies list of values that can be used in this fields (e.g. ‘cities’, ‘zip’, ‘states’, ‘airports’, etc.). See below on how to pull all the values for specified source.

INTEGER

textbox

slider

max

min

values (for slider)

 

REAL

textbox

max

min

 

DATE

textbox

 

 

EMAIL

textbox

 

 

ENUM

radio

select (pulldown)

slider

values

source

ENUM field can have one of the values specified under ‘values’  + user defined ‘other’ value.

OPTION

check

select (multi-select)

Values

OPTION field can have any number of values specified under ‘values’ (multi-select).

COMPLEX

-

 

Complex field can contain any number of simple fields under ‘complex_data’ section. In addition ‘complex_multi’ is used to specify if the complex section can be multi-instance.

IMAGE

 

 

Image uploader

This sections describes the feed operations.

  • GET /messages - Retrieve feed items
  • DELETE /messages/<message_id> - Delete feed items

GET /messages

Request:

GET : https://<host>/api/v1/messages?
  count=<max>&
  from=<from>&
  to=<to>&
  message_type=<filter>&
  gem_instance_id=<filter>&
        client_id=<Personal API key>

Authorization: Bearer <access_token>

Parameters:

  • ‘count’ – maximum number of messages to return
  • ‘from’/’to’ – range of messages ids to return (used for ‘get more’ functionality)
  • ‘message_type’ – filter for particular message type (see list below)
  • ‘gem_instance_id’ – filter for particular gem instance id

Response (JSON):

{
    "message": [
        {
            "message_id": "123456",
            "message_type": "<message type>",
            "message_contact_email": "john@personal.com",
            "message_contact_id": "<contact id>",
            "message_timestamp": 12345,
            "message_read": "<true/false>",
            "message": "<freetextmessagetodisplay>",
            "gem_template_id": "<templateid>",
            "gem_instance_id": "<instanceid>",
            "snapshot_name": "<snapshotname>",
            "snapshot_id": "<snapshotinstanceid>"
        }
    ]
}

Message types:

Message type (code)

Message name/description

Available actions

IDS

Incoming data share

View

Adopt

Add contact

ODS

Outgoing data share

Stop access

SIDS

Stopped incoming data share

No actions (information only)

SODS

Stopped outgoing data share

No actions (information only)

IDR

Incoming data request

Grant (if there is instance of gem)

Create and Grant (if there is not)

Ignore

ODR

Outgoing data request

No actions (information only)

DRI

Data request ignored

No actions (information only)

PAM

Profile (gem) addition message

View/Edit

Grant

Request

PCM

Profile (gem) creation message

View/Edit

Grant

Request

PFM

Profile (gem) fill message

View/Edit

Grant

Request

PDM

Profile (gem) adopt message

No actions (information only)

WME

Welcome message

No actions (information only)

OSM

Owner support message

No actions (information only)

PPM

Profile publish message

No actions (information only)

P3M

Generic message

No actions (information only)

 

Note: for all messages, either “gem_template_id” (requests) or “gem_instance_id” (all others) is mandatory.

 


DELETE /messages/{message_id}

Request:

DELETE : https://<host>/api/v1/messages/<message_id>?client_id=<Personal API key>
Authorization: Bearer <access_token>

This section describes public gem operations.

  • GET /snapshots
  • GET /snapshots/<public_gem_id>
  • GET /snapshot/counts

GET /snapshots

Get the list of community gems.

 

Resource(s):

List of community gems for specified template id:

GET : https://<host>/api/v1/snapshots/templates/<template id>[/count]?
  pagesize=< count – max/default is 100>&
  offset=<offset>&order=<order>&sort=<[asc/desc]>&
        client_id=<Personal API key> 

List of community gems for specified tag:

GET : https://<host>/api/v1/snapshots/tagged/<tag>[/count]
  pagesize=< count – max/default is 100>&
  offset=<offset>&order=<order>&sort=<[asc/desc]>

List of community gems for specified owner id:

GET : https://<host>/api/v1/snapshots/owners/<owner username>[/count]
  pagesize=<count – max/default is 100>&
  offset=<offset>&order=<order>&sort=<[asc/desc]>&
        client_id=<Personal API key> 

Returns (JSON):

{
    "snapshots": [
        {
            "tags": [
                "<tag1>",
                "<tag2>"
            ],
            "description": "<description> ",
            "time_to_complete": "<time to complete>",
            "snapshot_name": "<snapshot name>",
            "id": "<public_gem_id>",
            "template_id": "<templateid>",
            "created": 54324234,
            "updated": 54324234
        }
    ]
}

GET /snapshot/{public_gem_id}

Request:

GET : https://<host>/api/v1/snapshot/<public_gem_id>?client_id=<Personal API key>

Response (JSON):

{
    "snapshot_info": {
        "tags": [
            "<tag1>",
            "<tag2>"
        ],
        "description": "<description> ",
        "time_to_complete": "<time to complete>",
        "snapshot_name": "<snapshot name>",
        "id": "<public_gem_id>",
        "template_id": "<templateid>",
        "created": 12343,
        "updated": 23423
    },
    "snapshot": {
        "#": "Standard data format"
    }
}

GET /snapshot/counts

Get the number of community gems.

 

Resource(s):

Count of community gems for each of the templates:

GET : https://<host>/api/v1/snapshots/counts/template?client_id=<Personal API key>

Returns (JSON):

{[
 {
  "id": "<gem_template_id>",
  "count": 12
 }
 ]}

Count of community gems for each user (top 100 users):

GET : https://<host>/api/v1/snapshots/counts/user?client_id=<Personal API key>

Returns (JSON):

{[
 {
  "username": "<user>",
  "count": 23
 }
 ]}

Count of community gems for each of the tags (top 100 tags):

GET : https://<host>/api/v1/snapshots/counts/tag?client_id=<Personal API key>

Returns (JSON):

{[
 {
  "tag": "<tag>",
  "count": 43
 }
 ]}

This section describes how to manage avatar images.

  • GET /avatar/<user_id>

GET /avatar/{user_id}

Get the avatar image for a user. Use the Client Credential Flow access token.

GET : https://<host>/avatar/<user_id>?[size=<24,30,50,75,100,120>]
Authorization: Bearer <access_token> 


When retrieving the user’s own avatar, you can replace the "user_id" with "me":

GET : https://<host>/avatar/me?[size=<24,30,50,75,100,120>]
Authorization: Bearer <access_token> 

This section describes the contact and contact group operations.

Contact

  • GET /contact - Retrieve a list of contacts
  • PUT /contact/<contact_id> - Edit a contact's info
  • GET /contact/<contact_id>/access/ - Retrieve list of gem instances a contact has granted and recieved
  • POST /contact - Create new contact
  • DELETE /contact/<contact_id> - Delete a contact

Contact Group

  • GET /contact_groups - Retrieve all the system and custom (user-generated) groups
  • PUT /contact_groups/<custom group name> - Update the name of a custom group
  • POST /contact_groups - Create a new custom group
  • DELETE /contact_groups/{custom group name} - Delete a custom group
  • GET /contact_group/{group name} - Retrieve the contacts in a group (note there is NO S on contact_group)
  • PUT /contact_group/{group name}/add/{contact_user_id} - Add a contact to a group (note there is NO S in contact_group)
  • PUT /contact_group/{group name}/delete/{contact_user_id} - Delete a contact from a group (note there is NO S in contact_group)

GET /contact

Gets the list of a users' contacts.

Request:

GET : https://<host>/api/v1/contact?client_id=<Personal API key>
Authorization: Bearer <access_token>

 

Response (JSON):

{
    "contact": [
        {
            "id": "d41b3d2f-fe15-4f73-a161-c8755847096a",
            "firstname": "John",
            "lastname": "Smith",
            "email": "john@personal.com",
            "username": "johns",
            "contact_avatar": "https://… <path to avatar>",
            "groups:": [
                "group #1",
                "group #2",
                "group #3"
            ]
        }
    ]
}

PUT /contact/{contact_id}

Updates the first name and last name for an existing contact.

Request:

PUT : https://<host>/api/v1/contact/<contact_id>?client_id=<Personal API key>
Authorization: Bearer <access_token>

Request body (JSON):

{
    "contact": {
        "firstname": "John",
        "lastname": "Smith",
        "#": "E-mail address cannot be updated in existing contact"
    }
}

Response:

Success/Failure + JSON

POST /contact

Creates new contact(s).

Request:

POST : https://<host>/api/v1/contact?client_id=<Personal API key>
Authorization: <access_token>

Request body (JSON):

{
    "contact": [
        {
            "firstname": "John",
            "lastname": "Smith",
            "#": "Note: either‘email’ or ‘username’ is required. Other parameters are optional",
            "email": "john@personal.com",
            "username": "johns"
        }
    ]
}

Response:

 

{
    "errors": [
        {
            "error": "…",
            "error_description": "<email address that failed>"
        }
    ],
    "contact": [
        {
            "id": "d41b3d2f-fe15-4f73-a161-c8755847096a",
            "firstname": "John",
            "lastname": "Smith",
            "email": "john@personal.com",
            "phone": "1234567890",
            "username": "johns",
            "contact_avatar": "https://… <path to avatar>",
            "groups:": [
                "group #1",
                "group #2",
                "group #3"
            ]
        }
    ]
}

DELETE /contact/{contact_id}

Deletes an existing contact.

Request:

DELETE : https://<host>/api/v1/contact/<contact_id>?client_id=<Personal API key>
Authorization: Bearer <access_token>

Response:

Success/Failure


GET /contact_groups

Retrieves the list of contact groups. Note that some of the contact groups are named by the system, and some are named by the user.

Request:

 GET: https://<host>/api/v1/contact_groups?client_id=<Personal API key>
 Authorization: Bearer <access token>

Response (JSON):

 

{
    "custom": [
        "Custom Group Name 1",
        "Custom Group Name 2"
    ],
    "system": [
        "Acquaintances",
        "Close Family",
        "Co-Workers",
        "Family",
        "Friends"
    ]
}

PUT /contact_groups/{custom group name}

Updates existing custom contact group name. Note that there can be spaces in some custom group names.

Request + body (JSON):

PUT: https://<host>/api/v1/contact_groups/<custom group name>?client_id=<Personal API key>
Authorization: Bearer <access token>

{
 “name”: “My New Custom Group Name”
}

Returns:

Success/Failure + JSON


POST /contact_groups

Creates new custom contact group. 

Request + body (JSON):

POST: https://<host>/api/v1/contact_groups?client_id=<Personal API key>
Authorization: Bearer <access token>

{
 “name”: “My custom group”
}

Response:

Success/Failure + JSON


DELETE /contact_groups/{custom group name}

Deletes existing custom contact group. 

Request:

DELETE: https://<host>/api/v1/contact_groups/<custom group name>?client_id=<Personal API key>
Authorization: Bearer <access token>

Returns:

Success/Failure + JSON.


GET /contact_group/{group name}

Get list of contacts in a group.

Request. Note that there is NO S in contact_group:

GET: https://<host>/api/v1/contact_group/<group name>?client_id=<Personal API key>
Authorization: Bearer <access token>

Response (JSON):

{
    "contact": [
        {
            "id": "d41b3d2f-fe15-4f73-a161-c8755847096a",
            "firstname": "John",
            "lastname": "Smith",
            "email": "john@personal.com",
            "username": "johns",
            "contact_avatar": "https://… <path to avatar>",
            "groups:": [
                "group #1",
                "group #2",
                "group #3"
            ]
        }
    ]
}

PUT /contact_group/{group name}/add/{contact_user_id}

Adds a contact to a group.

Request. Note that there is NO S in contact_group:

 PUT: https://<host>/api/v1/contact_group/<group name>/add/<contact_user_id>?client_id=<Personal API key>
 Authorization: Bearer <access token>

Returns:

Success /Failure 

 

PUT /contact_group/{group name}/delete/{contact_user_id}

Removes a contact from a group.

Request. Note that there is NO S in contact_group:

 PUT: https://<host>/api/v1/contact_group/<group name>/delete/<contact_user_id>?client_id=<Personal API key>
 Authorization: Bearer <access token> 

Returns:

Success /Failure 

Status API Training Shop Blog About © 2016 GitHub, Inc. Terms