miiCard Directory API

The miiCard Directory API lets your application discover miiCard members who have published a public profile page and elected to be found by the directory service.

You don't need any OAuth tokens nor a developer account - just query the API and parse the responses.

What is the miiCard Directory?

The miiCard Directory is a way of interrogating the published public profile pages of miiCard members using standard HTTP calls to an endpoint that returns simple JSON output. It lets you:

  • Get a JSON representation of the information published on a given public profile page
  • Search for a miiCard member by data they've published on their public profile
  • Search by a hash of known data for enhanced privacy

To be found in the Directory, a miiCard member must have:

  • Published their public profile
  • Enabled their profile for discoverability - this is the default for new accounts when a public profile page is published for the first time, but needs to be performed explicitly for accounts created earlier than October 1st 2013

Try it out

Expand/collapse hashing controls

Query URL




Querying the Directory

There's no authentication required to query the Directory API, just simple HTTP requests and JSON responses.

Endpoint https://sts.miicard.com/api/v1/Members
Content-Type application/json
JSONP support Use the callback query parameter
CORS support Enabled for supporting browsers
Caching Results are cached for 10 minutes during which time changes to the member's profile data may not be reflected in the Directory API response

Arguments to the Directory API are supplied as query string parameters:

username Finds a member by their miiCard username
email Finds a member by their email address
phone Finds a member by their phone number. The phone number must be formatted as [country code][national number without leading zero], optionally including a leading +. For example, the following are valid:
447700900111 (preferred)
twitter Finds a member by their Twitter handle, or their Twitter URL. The following are all valid values for a Twitter query:
facebook Finds a member by their Facebook profile URL
linkedin Finds a member by their non-localised LinkedIn profile URL - i.e. http://uk.linkedin.com/in/username would become http://www.linkedin.com/in/username
liveid Finds a member by their Microsoft ID URL
google Finds a member by their Google+ ID or their Google+ profile URL
ebay Finds a member by their eBay username or their eBay 'my.ebay.com' profile URL
veritasvitae Finds a member by their Veritas Vitae VV number of profile URL
domain Finds a member by a domain name that they've published on their profile page.

Response examples

Expect a JSON encoded MiiApiResponse of MiiUserProfile - naming and structure is as the linked documentation.

Successful response

Query: https://sts.miicard.com/api/v1/Members?twitter=@pauloneilluk


  "Data": {
    "Age": null,
    "CardImageUrl": "https:\/\/my.miicard.com\/img\/pablissimo.png",
    "DateOfBirth": null,
    "EmailAddresses": [
        "Verified": true,
        "Address": "Paul.ONeill@miicard.com",
        "DisplayName": "pablissimo",
        "IsPrimary": true
    "FirstName": "Paul",
    "HasPublicProfile": true,
    "Identities": [
        "Verified": true,
        "ProfileUrl": "http:\/\/twitter.com\/PaulONeillUK",
        "Source": "Twitter",
        "UserId": "134483922"
        "Verified": true,
        "ProfileUrl": "http:\/\/www.linkedin.com\/in\/oneillpaul",
        "Source": "LinkedIn",
        "UserId": "HEXw_9dnbe"
    "IdentityAssured": true,
    "LastName": "O'Neill",
    "LastVerified": "\/Date(1381039378453)\/",
    "MiddleName": null,
    "PhoneNumbers": null,
    "PostalAddresses": null,
    "PreviousFirstName": null,
    "PreviousLastName": null,
    "PreviousMiddleName": null,
    "ProfileShortUrl": "http:\/\/miicard.me\/Lw51Eqy8",
    "ProfileUrl": "https:\/\/my.miicard.com\/card\/pablissimo",
    "PublicProfile": null,
    "Qualifications": null,
    "Salutation": null,
    "Username": "pablissimo",
    "WebProperties": null
  "ErrorCode": 0,
  "ErrorMessage": null,
  "IsTestUser": false,
  "Status": 0

Failure response - no matching user

Query: https://sts.miicard.com/api/v1/Members?email=non-existent-user@example.com


  "Data": null,
  "ErrorCode": 11,
  "ErrorMessage": "No matches were found",
  "IsTestUser": false,
  "Status": 1

Failure response - invalid query criteria

Query: https://sts.miicard.com/api/v1/Members?invalid-attribute=example


  "Data": null,
  "ErrorCode": 10,
  "ErrorMessage": "There was no recognisable search criterion or the criterion had an empty value. Valid values are from the set {ebay, email, facebook, google, linkedin, liveid, phone, twitter, username, veritasvitae}",
  "IsTestUser": false,
  "Status": 1

Preserving privacy - hashed identifiers

While miiCard doesn't log queries made to the Directory API and only supports queries over HTTPS you may still wish to take the extra privacy-protecting step of supplying hashed identifiers rather than raw values. For example, rather than supplying the email address 'user@example.com' you may want to supply it as its SHA1 hex-formatted hash 63a710569261a24b3766275b7000ce8d7b32e2f7.

To use a hashed identifier with the Directory API:

  • Normalise the identifier as described in the table below
  • Hash the UTF-8 encoded bytes of the normalised identifier with SHA-1
  • Present the hash bytes to the Directory API as a lowercased hexadecimal string
  • Append the 'hashed=true' query string parameter

Unlike when a plaintext identifier is sent to the Directory API, such as a Twitter profile URL, miiCard is unable to do any parsing or normalisation of identifiers when sent as a hashed value. As such, you have to do this normalisation step yourself.

Criterion Normalisation steps
  • Lowercase the username or email address and ensure any leading or trailing whitespace has been eliminated

If you have a profile URL (for example https://twitter.com/miiCard)

  • Remove all but the last path component of the URL (here, 'miiCard')
  • Lowercase the result

If you have a username or handle, simply lowercase it.

  • For Twitter, strip any leading @ symbol

Given a profile URL:

  • Remove the protocol component of the URL - http://example.com/path becomes example.com/path
  • Strip any trailing forward slash
  • Lowercase the result

Given a profile URL:

  • If the URL is localised (i.e the host isn't www.linkedin.com) then replace it with www.linkedin.com
  • Remove the protocol component of the URL - http://www.linkedin.com/in/username becomes www.linkedin.com/in/username
  • Strip any trailing forward slash
  • Lowercase the result
phone Using the example phone number +44 7700 900 100:
  • Extract or determine the country of the number and strip any leading + or zeros (here, 44)
  • Concatenate the remainder of the number, eliminating any whitespace (becoming 44700900100)
  • If the domain has been expressed as a URL, then strip the protocol component and path components, leaving just the host part - i.e. http://www.example.com/path becomes www.example.com
  • Lowercase the result

Step by step example - querying for 'User@example.com'

First, normalise the identifier - since this is an email address, we trim the string of whitespace then lowercase it giving us a normalised identifier of 'user@example.com'.

Then follow the remaining steps above:

  • Obtain the UTF-8 encoded bytes of the lowercased identifier, yielding a byte array
    [117, 115, 101, 114, 64, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109]
  • Hash the UTF-8 encoded bytes with SHA-1, yielding byte array of
    [99, 167, 16, 86, 146, 97, 162, 75, 55, 102, 39, 91, 112, 0, 206, 141, 123, 50, 226, 247]
  • Hex-encode the hash, lowercased, yielding 63a710569261a24b3766275b7000ce8d7b32e2f7
  • Form the query, appending hashed=true: