Add documentation
diff --git a/M-Pin SDK - Authentication flow.png b/M-Pin SDK - Authentication flow.png
new file mode 100644
index 0000000..c386255
--- /dev/null
+++ b/M-Pin SDK - Authentication flow.png
Binary files differ
diff --git a/M-Pin SDK - Authentication flow.xml b/M-Pin SDK - Authentication flow.xml
new file mode 100644
index 0000000..4bf06c0
--- /dev/null
+++ b/M-Pin SDK - Authentication flow.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<mxGraphModel dx="1050" dy="636" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="826" pageHeight="1169" background="#ffffff" math="0"><root><mxCell id="0"/><mxCell id="1" parent="0"/><mxCell id="2" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;" parent="1" source="3" target="5" edge="1"><mxGeometry x="414" y="130" as="geometry"/></mxCell><mxCell id="3" value="Start" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1"><mxGeometry x="379" y="90" width="70" height="40" as="geometry"/></mxCell><mxCell id="25" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;entryX=0.5;entryY=0;" parent="1" source="5" target="23" edge="1"><mxGeometry relative="1" as="geometry"><Array as="points"/></mxGeometry></mxCell><mxCell id="5" value="&lt;font face=&quot;Lucida Console&quot;&gt;StartAuthentication&lt;/font&gt;" style="whiteSpace=wrap;html=1;" parent="1" vertex="1"><mxGeometry x="342" y="180" width="144" height="40" as="geometry"/></mxCell><mxCell id="9" value="&lt;code&gt;&lt;font face=&quot;Lucida Console&quot;&gt;OK&lt;/font&gt;&lt;/code&gt;" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" parent="1" source="23" target="19" edge="1"><mxGeometry as="geometry"><mxPoint y="3" as="offset"/><mxPoint x="414" y="449.6715328467153" as="sourcePoint"/><mxPoint x="414" y="371" as="targetPoint"/><Array as="points"/></mxGeometry></mxCell><mxCell id="18" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;entryX=0.5;entryY=0;exitX=0.5;exitY=1;" parent="1" source="19" target="21" edge="1"><mxGeometry x="414" y="763" as="geometry"><Array as="points"/></mxGeometry></mxCell><mxCell id="19" value="Read Secret (PIN)&lt;div&gt;from end user&lt;/div&gt;" style="whiteSpace=wrap;html=1;" parent="1" vertex="1"><mxGeometry x="354" y="383" width="120" height="40" as="geometry"/></mxCell><mxCell id="37" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;" parent="1" source="21" target="36" edge="1"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="21" value="&lt;p&gt;&lt;code&gt;&lt;font face=&quot;Lucida Console&quot; style=&quot;font-size: 12px&quot;&gt;FinishAuthentication&lt;/font&gt;&lt;/code&gt;&lt;/p&gt;" style="whiteSpace=wrap;html=1;" parent="1" vertex="1"><mxGeometry x="330" y="483" width="168" height="40" as="geometry"/></mxCell><mxCell id="22" value="End" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1"><mxGeometry x="379" y="759.5999999999999" width="70" height="40" as="geometry"/></mxCell><mxCell id="27" value="&lt;span&gt;&lt;font face=&quot;Lucida Console&quot;&gt;REVOKED&lt;/font&gt;&lt;/span&gt;" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;entryX=0;entryY=0.5;" parent="1" source="23" target="28" edge="1"><mxGeometry x="-0.04" y="15" relative="1" as="geometry"><mxPoint x="582" y="315" as="targetPoint"/><Array as="points"/><mxPoint as="offset"/></mxGeometry></mxCell><mxCell id="23" value="Status?" style="rhombus;whiteSpace=wrap;html=1;" parent="1" vertex="1"><mxGeometry x="366" y="265" width="95" height="60" as="geometry"/></mxCell><mxCell id="30" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;entryX=1;entryY=0.5;exitX=0.5;exitY=1;" parent="1" source="28" target="22" edge="1"><mxGeometry relative="1" as="geometry"><mxPoint x="637" y="435" as="targetPoint"/><Array as="points"><mxPoint x="637" y="780"/></Array></mxGeometry></mxCell><mxCell id="28" value="User is Revoked" style="whiteSpace=wrap;html=1;" parent="1" vertex="1"><mxGeometry x="580" y="275" width="114" height="40" as="geometry"/></mxCell><mxCell id="39" value="&lt;font face=&quot;Lucida Console&quot;&gt;OK&lt;/font&gt;" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;" parent="1" source="36" target="22" edge="1"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="41" value="&lt;span&gt;&lt;font face=&quot;Lucida Console&quot;&gt;INCORRECT_PIN&lt;/font&gt;&lt;/span&gt;" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;" parent="1" source="36" target="40" edge="1"><mxGeometry x="-0.08" y="-12" relative="1" as="geometry"><mxPoint as="offset"/></mxGeometry></mxCell><mxCell id="36" value="Status?" style="rhombus;whiteSpace=wrap;html=1;" parent="1" vertex="1"><mxGeometry x="366" y="573" width="95" height="65" as="geometry"/></mxCell><mxCell id="43" value="&lt;font face=&quot;Lucida Console&quot;&gt;REGISTERED&lt;/font&gt;" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;entryX=0;entryY=0.5;exitX=0.5;exitY=0;" parent="1" source="40" target="19" edge="1"><mxGeometry x="-0.5393" relative="1" as="geometry"><mxPoint x="218.5" y="733" as="targetPoint"/><Array as="points"><mxPoint x="219" y="403"/></Array><mxPoint as="offset"/></mxGeometry></mxCell><mxCell id="48" value="&lt;font face=&quot;Lucida Console&quot;&gt;BLOCKED&lt;/font&gt;" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;entryX=0.5;entryY=0;" parent="1" source="40" target="46" edge="1"><mxGeometry relative="1" as="geometry"><Array as="points"/></mxGeometry></mxCell><mxCell id="40" value="User State?" style="rhombus;whiteSpace=wrap;html=1;" parent="1" vertex="1"><mxGeometry x="171" y="573" width="95" height="65" as="geometry"/></mxCell><mxCell id="50" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;entryX=0;entryY=0.5;exitX=0.5;exitY=1;" parent="1" source="46" target="22" edge="1"><mxGeometry relative="1" as="geometry"><mxPoint x="219" y="1090" as="targetPoint"/><Array as="points"><mxPoint x="219" y="780"/></Array></mxGeometry></mxCell><mxCell id="46" value="User is Blocked&lt;div&gt;(need to re-register)&lt;/div&gt;" style="whiteSpace=wrap;html=1;" parent="1" vertex="1"><mxGeometry x="159" y="690" width="120" height="40" as="geometry"/></mxCell></root></mxGraphModel>
\ No newline at end of file
diff --git a/M-Pin SDK - Registration flow.png b/M-Pin SDK - Registration flow.png
new file mode 100644
index 0000000..460f6f9
--- /dev/null
+++ b/M-Pin SDK - Registration flow.png
Binary files differ
diff --git a/M-Pin SDK - Registration flow.xml b/M-Pin SDK - Registration flow.xml
new file mode 100644
index 0000000..fdf50b7
--- /dev/null
+++ b/M-Pin SDK - Registration flow.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<mxGraphModel dx="1050" dy="636" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="826" pageHeight="1169" background="#ffffff" math="0"><root><mxCell id="0"/><mxCell id="1" parent="0"/><mxCell id="41519c7962ced28-4" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;" edge="1" parent="1" source="41519c7962ced28-1" target="41519c7962ced28-2"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="41519c7962ced28-1" value="Start" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1"><mxGeometry x="379" y="90" width="70" height="40" as="geometry"/></mxCell><mxCell id="41519c7962ced28-8" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="41519c7962ced28-2" target="41519c7962ced28-6"><mxGeometry relative="1" as="geometry"><mxPoint x="405.5" y="330" as="targetPoint"/><Array as="points"/></mxGeometry></mxCell><mxCell id="41519c7962ced28-2" value="&lt;font face=&quot;Lucida Console&quot;&gt;MakeNewUser&lt;/font&gt;" style="whiteSpace=wrap;html=1;" vertex="1" parent="1"><mxGeometry x="366" y="180" width="95" height="40" as="geometry"/></mxCell><mxCell id="41519c7962ced28-10" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;" edge="1" parent="1" source="41519c7962ced28-6" target="41519c7962ced28-9"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="41519c7962ced28-6" value="&lt;font face=&quot;Lucida Console&quot;&gt;StartRegistration&lt;/font&gt;" style="whiteSpace=wrap;html=1;" vertex="1" parent="1"><mxGeometry x="347" y="270" width="133" height="40" as="geometry"/></mxCell><mxCell id="41519c7962ced28-13" value="&lt;div&gt;&lt;span&gt;&lt;font face=&quot;Lucida Console&quot;&gt;STARTED_REGISTRATION&lt;/font&gt;&lt;/span&gt;&lt;br&gt;&lt;/div&gt;" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="41519c7962ced28-9" target="41519c7962ced28-11"><mxGeometry x="-0.1333" y="15" relative="1" as="geometry"><mxPoint x="582" y="405" as="targetPoint"/><Array as="points"><mxPoint x="617" y="405"/></Array><mxPoint as="offset"/></mxGeometry></mxCell><mxCell id="41519c7962ced28-16" value="&lt;code&gt;&lt;font face=&quot;Lucida Console&quot;&gt;ACTIVATED&lt;/font&gt;&lt;/code&gt;" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;" edge="1" parent="1" source="41519c7962ced28-9" target="41519c7962ced28-15"><mxGeometry x="0.0139" y="-18" relative="1" as="geometry"><mxPoint x="18" y="-18" as="offset"/></mxGeometry></mxCell><mxCell id="41519c7962ced28-9" value="If returned&lt;div&gt;Status is OK,&amp;nbsp;&lt;span style=&quot;line-height: 1.2&quot;&gt;Check&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;line-height: 1.2&quot;&gt;User State&lt;/span&gt;&lt;/div&gt;" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="1"><mxGeometry x="345" y="360" width="137" height="90" as="geometry"/></mxCell><mxCell id="41519c7962ced28-18" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;entryX=0.75;entryY=0;exitX=0.5;exitY=1;" edge="1" parent="1" source="41519c7962ced28-11" target="41519c7962ced28-15"><mxGeometry relative="1" as="geometry"><mxPoint x="617" y="590" as="targetPoint"/><Array as="points"><mxPoint x="617" y="520"/><mxPoint x="450" y="520"/></Array></mxGeometry></mxCell><mxCell id="41519c7962ced28-11" value="Wait for user to confirm identity" style="whiteSpace=wrap;html=1;" vertex="1" parent="1"><mxGeometry x="560" y="450" width="114" height="40" as="geometry"/></mxCell><mxCell id="41519c7962ced28-20" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;" edge="1" parent="1" source="41519c7962ced28-15" target="41519c7962ced28-19"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="41519c7962ced28-15" value="&lt;font face=&quot;Lucida Console&quot;&gt;ConfirmRegistration&lt;/font&gt;" style="whiteSpace=wrap;html=1;" vertex="1" parent="1"><mxGeometry x="342" y="545" width="144" height="40" as="geometry"/></mxCell><mxCell id="41519c7962ced28-22" value="&lt;span&gt;&lt;font face=&quot;Lucida Console&quot;&gt;IDENTITY_NOT_VERIFIED&lt;/font&gt;&lt;/span&gt;" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;entryX=0.75;entryY=0;exitX=1;exitY=0.5;" edge="1" parent="1" source="41519c7962ced28-19" target="41519c7962ced28-11"><mxGeometry x="-0.6526" y="15" relative="1" as="geometry"><mxPoint x="583" y="695" as="targetPoint"/><Array as="points"><mxPoint x="710" y="660"/><mxPoint x="710" y="410"/><mxPoint x="646" y="410"/></Array><mxPoint as="offset"/></mxGeometry></mxCell><mxCell id="41519c7962ced28-24" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;" edge="1" parent="1" source="41519c7962ced28-19" target="41519c7962ced28-23"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="41519c7962ced28-19" value="Status?" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="1"><mxGeometry x="345" y="615" width="137" height="90" as="geometry"/></mxCell><mxCell id="41519c7962ced28-26" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;entryX=0.5;entryY=0;exitX=0.5;exitY=1;" edge="1" parent="1" source="41519c7962ced28-23" target="41519c7962ced28-25"><mxGeometry relative="1" as="geometry"><Array as="points"/></mxGeometry></mxCell><mxCell id="41519c7962ced28-23" value="Read Secret (PIN)&lt;div&gt;from end user&lt;/div&gt;" style="whiteSpace=wrap;html=1;" vertex="1" parent="1"><mxGeometry x="354" y="750" width="120" height="40" as="geometry"/></mxCell><mxCell id="41519c7962ced28-29" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="41519c7962ced28-25" target="41519c7962ced28-27"><mxGeometry relative="1" as="geometry"><mxPoint x="413.5" y="1000" as="targetPoint"/><Array as="points"/></mxGeometry></mxCell><mxCell id="41519c7962ced28-25" value="&lt;font face=&quot;Lucida Console&quot;&gt;FinishRegistration&lt;/font&gt;" style="whiteSpace=wrap;html=1;" vertex="1" parent="1"><mxGeometry x="342" y="848" width="143" height="40" as="geometry"/></mxCell><mxCell id="41519c7962ced28-27" value="End" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1"><mxGeometry x="379" y="944.5999999999999" width="70" height="40" as="geometry"/></mxCell></root></mxGraphModel>
\ No newline at end of file
diff --git a/README.md b/README.md
index 7bdcacf..b51938b 100644
--- a/README.md
+++ b/README.md
@@ -58,8 +58,8 @@
 mpin.waitForMobileAuth(<timeout-sec>, <retry-period-sec>, <callback>);
 
 /*
-   If successfull - Authentication completed
-   If exits with timeout, then no successfull authentication from mobile device was completed
+   If successful - Authentication completed
+   If exits with timeout, then no successful authentication from mobile device was completed
    If one needs to cancel the waiting for authentication from the mobile device, call cancelMobileAuth()
 */
 ```
@@ -81,3 +81,267 @@
 Actively tested with node:
 
   - 0.10.4
+
+## mpinjs API Reference
+
+### Errors
+
+Errors are returned as objects in callback functions where such are available, and they have the general structure:
+```js
+{
+   code: <error-code>,
+   type: <error-desc>,
+   message: <optional-message>
+}
+```
+as:
+
+| Field | Type | Notes | Description |
+|:----- |:---- |:----- |:----------- |
+| `code` | `Number` | Mandatory | Internal error code |
+| `type` | `String` | Mandatory | Predefined error description |
+| `message` | `String` | Optional | Additional error message where applicable |
+
+The list of errors is:
+
+| Error code | Error desc | Explanation |
+|:---------- |:---------- |:----------- |
+| `0` | `"MISSING_USERID"` | User ID was not proceeded to the API, while it was required |
+| `1` | `"INVALID_USERID"` | The user ID that was provided to the API is not valid or not existing |
+| `2` | `"MISSING_PARAMETERS"` | A required parameter was not provided to the API. Usually an additional explanation _message_ will be provided with this error |
+| `3` | `"IDENTITY_NOT_VERIFIED"` | `confirmRegistration()` was called while the identity is still not verified |
+| `4` | `"IDENTITY_MISSING"` | No user with the provided user ID has been created |
+| `5` | `"WRONG_PIN"` | The provided user secret (PIN or password) is wrong and authentication failed |
+| `6` | `"WRONG_FLOW"` | The API method was called not according to the correct flow and the provided user has the wrong state  |
+| `7` | `"USER_REVOKED"` | A time permit for the user couldn't be retrieved and the user is considered "revoked" by the system |
+| `8` | `"TIMEOUT_FINISH"` | The call `waitForMobileAuth()` has ended with timeout and no successful authentication has been done during that time from a mobile device |
+
+### The User object
+
+For each user an object needs to be created. The key to the user object is its identity, which is supposed to be unique. The user object has a _State_ which basically indicates what can be done with the user. For instance, if a user has not been registered, it cannot be authenticated, obviously. The different user states are:
+
+| State | Description |
+| ----- | ----------- |
+| `"INVALID"` | A user that has just been created and no registration process has been started for it |
+| `"STARTED"` | The registration process for this user has been started, but the identity is still not verified |
+| `"ACTIVATED"` | A user which has been made active without a need of extra identity verification step |
+| `"REGISTERED"` | The user registration process has been completed and its secret (password or PIN) has been successfully set. Such a user can be authenticated |
+| `"BLOCKED"` | A user which authentication failed several time in a row and has been blocked by the server. Such user cannot authenticate anymore and need to re-register |
+
+### mpinjs API
+
+#### Callbacks
+
+Some of the API methods have a `callback` parameter. The convention for the callback function is:
+```js
+function(error, data)
+```
+as:
+* `error` is an error object as described above, or `null` if no error has occurred.
+* `data` is the returned data for the API method. In some cases it might be just 'true' to indicate that the method succeeded, while in others it could be an object carrying some result.
+
+The standard error handling would be as follows:
+```js
+<some-api-method>( userId, function(err, data) {
+    if (err) {
+        // Method failed with some error
+    } else {
+        // Method succeeded, proceed with handling data
+    }
+});
+```
+
+##### `mpinjs(options)`
+
+An `mpinjs` instance is constructed as follows:
+```js
+mpin = new mpinjs({
+    server: "http://ec2-54-77-232-113.eu-west-1.compute.amazonaws.com",
+    rpsPrefix: "rps"
+})
+```
+A key/value list of parameters is passed to the constructor as the currently recognized parameters are:
+* `server` - _Mandatory_. The address at which the M-Pin Service is accessible. This is usually the address of the Relying Party Application. For instance if the backend is an M-Pin SSO server this would be the address of that server.
+* `rpsPrefix` - _Optional_. This parameter could be specified in case `rpsPrefix` parameter in the RPS configuration has been changed and is not the default one. If this option is not specified, then the default `"rps"` is used.
+
+##### `init(callback)`
+
+This method will attempt to initialize the `mpinjs` instance according the provided options and retrieve users from the storage. It makes a request to retrieve the _Client Settings_ from the server. If the method succeeds, it will return the retrieved client settings as the `data` in the callback function.
+ 
+#### User management API
+
+##### `makeNewUser(userId, deviceId)`
+
+This method will create a new user object in the internal user storage. The new user will be initialized with the _state_ `"INVALID"`. The received parameters are:
+* `userId` - _Mandatory_, String - The identity of the new user. It should be unique for the given server / application. The user object could later on be referred to using this user identity. 
+* `deviceId` - _Optional_, String - Some description of the local device. This Device ID is passed to the RPA, which might store it and use it later to determine which M-Pin ID is associated with this device.
+
+##### `listUsers()`
+
+This method will return a list of all the user objects that `mpinjs` has in its storage. The user objects are of the form:
+```js
+{
+    userId: <user-identity>,
+    deviceId: <device-id>,
+    state: <user-state>
+}
+```
+##### `checkUser(userId)`
+
+This method will return `true` if a user object with the given `userId` exists, or `false` if not.
+
+##### `getUser(userId, property)`
+
+This method will return either the user object that is associated with the given `userId`, or if `property` is specified it will return just the value of that property of the user object.
+* `userId` - _Mandatory_, String - The user identity associated with the user object
+* `property` - _Optional_, String - One of `"deviceId"`, `"state"` or `"userId"`. If specified, only the value of the specified property will be returned. Otherwise the whole user object will be returned, according to the specification in `listUsers()`.
+
+##### `deleteUser(userId)`
+
+This function will delete the user object associated with the given `userId` from the internal storage
+
+#### Registration API
+
+##### `startRegistration(userId, callback)`
+
+Parameters:
+* `userId` - _Mandatory_, String - the user identity associated with the user that has to be registered.
+* `callback` - _Mandatory_, function(error,data) - The callback that will be called after the registration has been started. This parameter complies to the convention explained above.
+
+This method will start the registration process for the user with the identity `userId`. Such a user should be previously created with the `makeNewUser()` method and should be in _state_ `"INVALID"`. 
+
+After successful completion of this call the user should be in one of two states - `"STARTED"` or `"ACTIVATED"`. If the user is in state `"STARTED"`, then its identity needs to be verified according to the process chosen by the RPA. When this process is complete the method `confirmRegistration()` should be called to proceed with the registration process. If the user is in state `"ACTIVATED"`, then it was instantly made active by the RPA and `confirmRegistration()` could be called right away to continue with the registration process.
+
+##### `restartRegistration(userId, callback)`
+
+Parameters:
+* `userId` - _Mandatory_, String - the user identity associated with the user that has to be registered.
+* `callback` - _Mandatory_, function(error,data) - The callback that will be called after the registration has been started. This parameter complies to the convention explained above.
+
+This method will restart the registration process for the user with the identity `userId`. The registration process for the user should have been previously started with `startRegistration()` and the user object should be in _state_ `"STARTED"`. This method will cause the user identity verification to be restarted, i.e. if the verification is done by sending an e-mail, then a new e-mail will be sent.
+
+After successful completion of this call the user should stay in state `"STARTED"`, awaiting for the identity to be verified. After it is done, `confirmRegistration()` should be called to proceed with the registration process.
+
+##### `confirmRegistration(userId, callback)`
+
+Parameters:
+* `userId` - _Mandatory_, String - the user identity associated with the user which identity needs to be confirmed.
+* `callback` - _Mandatory_, function(error,data) - The callback that will be called after the method has been completed. This parameter complies to the convention explained above.
+
+This method attempts to retrieve the _Client Key_ for the user associated with the identity `userId`. The user is expected to be in one of two states - `"STARTED"` or `"ACTIVATED"`. If this is not the case, `"WRONG_FLOW"` error will be returned through the callback. If the user identity has not been verified and the _Client Key_ cannot be retrieved, `"IDENTITY_NOT_VERIFIED"` error will be returned through the callback. If the method has been completed successfully, then the user state is set to `"ACTIVATED"`. Afterwards, the desired secret (PIN or password) should be read from the end user and then `finishRegistration()` should be called to complete the user registration.
+
+##### `finishRegistration(userId, pin)`
+
+Parameters:
+* `userId` - _Mandatory_, String - the user identity associated with the user which registration process should be finalized.
+* `pin` - _Mandatory_, String - The user secret (PIN or password) that should be used while generating the _M-Pin Token_.
+
+This method will generate and store the _M-Pin Token_ using the _Client Key_ retrieved during `confirmRegistration()` and the provided `pin`. The user state has to be `"ACTIVATED"` and its _Client Key_ has to be previously retrieved. If those conditions are not met, the function will fail, returning a `"WRONG_FLOW"` error. If successful, the method will return `true` and the user state will be set to `"REGISTERED"`.
+
+#### Authentication API
+
+##### `startAuthentication(userId, callback)`
+
+Parameters:
+* `userId` - _Mandatory_, String - the user identity associated with the user that needs to be authenticated.
+* `callback` - _Mandatory_, function(error,data) - The callback that will be called after the method has been completed. This parameter complies to the convention explained above.
+
+This method will attempt to retrieve _Time Permits_ for the given user, as a first step in the authentication process. The user has to be in state `"REGISTERED"`. If this is not the case, `"WRONG_FLOW"` error will be returned through the callback. If the time permit cannot be retrieved for some reason, `"USER_REVOKED"` error will be returned.
+
+##### `finishAuthentication(userId, pin, callback)`
+
+Parameters:
+* `userId` - _Mandatory_, String - the user identity associated with the user that needs to be authenticated.
+* `pin` - _Mandatory_, String - the user secret (PIN or password) that should be used for the user authentication.
+* `callback` - _Mandatory_, function(error,data) - The callback that will be called after the method has been completed. This parameter complies to the convention explained above.
+
+This method will attempt to authenticate the user against the M-Pin Server, using the provided `pin`. The user needs to have a valid time permit, previously retrieved via the `startAuthentication()` method. If the user authentication fails, `"WRONG_PIN"` error will be returned through the callback. If the authentication failed several times sequentially (usually 3), the user might become "blocked". When this happens the user state will be set to `"BLOCKED"` and this user will no longer be able to authenticate. If the authentication was successful, the returned `error` through the callback will be `null` and any data that was passed back by the RPA in the authentication response, will be returned through the callback's `data` parameter. Note that this data is not mandatory and might also be `null` or empty.
+
+##### `finishAuthenticationOtp(userId, pin, callback)`
+
+Parameters:
+* `userId` - _Mandatory_, String - the user identity associated with the user that needs to be authenticated.
+* `pin` - _Mandatory_, String - the user secret (PIN or password) that should be used for the user authentication.
+* `callback` - _Mandatory_, function(error,data) - The callback that will be called after the method has been completed. This parameter complies to the convention explained above.
+
+This method is very similar to `finishAuthentication()`, but it is intended to be used when a _One Time Password_ (OTP) is intended to be generated by the server. Note that not all of the servers support that functionality and currently this type of authentication could only be used against M-Pin SSO servers. The authentication process is the same, but as a result the `data` provided in the callback will carry the OTP information as follows:
+```js
+{
+    otp: <otp>,
+    ttlSeconds: <time-to-live-sec>,
+    nowTime: <current-time-sec>,
+    expireTime: <expire-time-sec>
+}
+```
+* `otp` - String - the OTP returned by the server
+* `ttlSeconds` - Number - the OTP expiration period in seconds.
+* `nowTime` - Number - Current M-Pin system time in seconds since the Epoch
+* `expireTime` - Number - The M-Pin system time in seconds since the Epoch when the OTP will expire.
+
+##### `getAccessNumber(callback)`
+
+Parameters:
+* `callback` - _Mandatory_, function(error,data) - The callback that will be called after the method has been completed. This parameter complies to the convention explained above.
+
+This method should be used when the authentication is about to be carried out from a remote/mobile device. For this reason an _Access Number_ should be displayed to the end user, and this number should be used on the mobile device to authenticate the user and then associate the local browser session with the mobile authentication event. The Access Number has an expiration period, which also should be displayed to the user, normally in a count-down fashion. Upon successful completion, this method will return through the callback the following `data`:
+```js
+{
+    accessNumber: <access-number>,
+    ttlSeconds: <time-to-live-sec>,
+    localTimeStart: <current-time-sec>,
+    localTimeEnd: <expire-time-sec>
+}
+```
+
+##### `getQrUrl(prerollId, callback)`
+
+Parameters:
+* `prerollId` - _Optional_, String - an optional end-user ID that will be "embedded" into the QA code and will be pre-seeded to the Mobile App reading the QR code.
+* `callback` - _Mandatory_, function(error,data) - The callback that will be called after the method has been completed. This parameter complies to the convention explained above.
+
+This method should be used when the authentication is about to be carried out from a remote/mobile device. This is an alternative to the _Access Number_ explained above and thus is very similar to it.
+The retrieved URL should be encoded and displayed to the end-user in the form of a QR code, which could be scanned by a Mobile App. The QR code carries information regarding that associates the local browser session with the mobile authentication event.
+The QR Code URL has an expiration period, which also should be displayed to the user, normally in a count-down fashion. Upon successful completion, this method will return through the callback the following `data`:
+ 
+```js
+{
+    qrUrl: <qrcode-url>,
+    ttlSeconds: <time-to-live-sec>,
+    localTimeStart: <current-time-sec>,
+    localTimeEnd: <expire-time-sec>
+}
+```
+
+##### `waitForMobileAuth(timeoutSeconds, requestSeconds, callback, callbackStatus)`
+
+Parameters:
+* `timeoutSeconds` - _Mandatory_, Number - The whole period after which the waiting will time-out
+* `requestSeconds` - _Optional_, Number - The period for re-attempting to poll for valid authentication from a mobile device. If not specified, the default value will be 3 seconds.
+* `callback` - _Mandatory_, function(error,data) - The callback that will be called after the method has been completed. This parameter complies to the convention explained above.
+* `callbackStatus` - _Optional_, function(data) - A status callback that is called by this method in order to update the caller about any change of waiting status.
+
+This method should be used when the authentication is about to be carried out from a remote/mobile device. After an _Access Number_ or a _QR Code URL_ has been retrieved and displayed to the end user, the client should wait for an authentication from a remote/mobile device. Calling this method will initiate such an awaiting. The method will poll for a successful authentication each `requestSeconds` and if no such authentication happened will finally fail after `timeoutSeconds`. When this happens, the `error` returned through the callback will be `"TIMEOUT_FINISH"`. If successful, the function will return through the callback the same values expected after successful `finishAuthentication()`.
+This method will also call `callbackStatus`, if provided, to update for any change of the waiting status. `callbackStatus` should exit normally, so the control returns back to `waitForMobileAuth`, which will continue waiting.
+The data provided to `callbackStatus` has the form:
+```js
+{
+  status: <status>,
+  statusCode: <statis-code>,
+  userId: <user-id>
+}
+```
+* `status` - either `"wid"` or `"user"`. Status `"wid"` means that the QR code has been scanned, while `"user"` means that the user ID that attempts to authenticate has been provided.
+* `statusCode` - a numeric code for the current status. It would normally be 0 meaning that no errors had occurred.
+* `userId` - would be empty when the `status` is `"wid"` and if the `status` is `"user"` it will be the identity of the user that is attempting to authenticate.       
+
+##### `cancelMobileAuth()`
+
+This method should be used when the authentication is about to be carried out from a remote/mobile device. This method will prematurely cause the `waitForMobileAuth()` to stop and exit. This might be necessary if the end user decides to navigate away from the UI page where the waiting for mobile authentication has been initiated. this method always succeeds.
+
+### Main Flows
+
+##### User Registration
+![*](./M-Pin SDK - Registration flow.png)
+
+##### User Authentication
+![*](./M-Pin SDK - Authentication flow.png)
\ No newline at end of file