FD1 Client Protocol
 
Library Developer Home FD1 Client Protocol Home Concepts Reading Data Writing Data Protocol Defined Servers Connect & Authenticate Proxies & Tunnels
Webhooks Programming Support Logging Minor Facts State Facts Response Format How To Guides eCommerce Sites Custom Point of Sale Customer Access Bulk Downloads Major APIs / Endpoints All Endpoints Products Sales SalesBuilder Session Sale Capture General Purpose Data Capture Devices Barcode Scanners Eftpos IoT Sensors Power Outlets Printing Scales Security Cameras Purchasing / Supply Side Purchase Orders Invoices Invoice Payments Document Capture Rare APIs / Endpoints SSL Certificates API Key Management Diagnositics Server to Client Messages Overview Resources / Objects Purchase Order Invoice Payable Invoice Payment Product Supplier Location Sale Lines Sale Delivery Details Sales Price Maps Employees Carriers Payments Product Kits Department 1 Customers

FD1 Session

Functions relating to a connection Session. These calls are primarily intended for WebSockets; if you are using HTTP GET/POST/PUT interfaces then session information is passed with HTTP headers.

fd1.session.login

TypeWrite
HTTPPOST

Transmits your login credentials to the server, typically authorising your data access. If you are using a websocket, then your first "send" should be a fd1.session.login packet. This also applies if you reconnect due to network drop out - another session login is required as you may connect to a different server.

You MUST send a valid fd1.session.login before FD1 will allow any other endpoints to be activated.

You MAY send multiple session.login commands, these are added to the scope you are allowed

There are several methods of authentication available. The server may enable/disable/enforce your selection.

MethodProsConsNotes
Simple API Key
  • Easy to implement for computers
  • Security is based around keeping the API key secret
Most servers will enforce GEO restriction or source IP address on APIkeys. If a key is authorised for Australia and is presented by a user from Brazil, the authorisation will fail.
Scanned QR Code
  • Great for sharing with customers or placing in store to allow "no password" access.
  • Security is based around physical secrecy of the QR code.
  • The QR code doesn't need to be scanned, an attacker only needs to know its value somehow
Most servers will enforce GEO restriction QR codes. If your store is in Fiji and the network request presenting the QR code comes from France, the authorisation will fail.
Non Transmitted Password
  • Requires HTTPS style connections, although this is isn't enforced.
  • Reasonable level of security for login pages
  • Password is not directly transmitted over the network
  • Requires HTTPS style connections, although this is isn't enforced.
Proof of Key
  • Suitable for applications as alternative to simple api-key
  • High level of security
  • Password is not directly transmitted over the network
  • Not practical for web browsers
  • Requires specific code to implement
Proof of key involves each end being provided with a reasonable sized random key (say 1Mb).
Through a series of steps each end barter to verify that both ends have the key, but without sending the complete key.

Example


A normal login using an ApiKey

{
  a: "fd1.session.login",
  v: {
    apikey: "ABAabfjhfh40584g5hfgge5756"
  }
}

A login using a QR code. A QR code login may be used by customers directly to access a very specific subset of data, such as a receipt or product information

{
  a: "fd1.session.login",
  v: {
    qr: "https://mycoolwebsite.xyz/welcome.htm?fd1=akajsh59585h5gfiu4b5utg568rg5h65g6h5"
  }
}

A username/password login where the password is not transmitted over the network

Step 1. Request a server supplied nonce/token

{
  a: "fd1.session.login",
  v: {
    method: "user/pass",
    user: "bob@example.com"
  }
}

Wait for server response containing the nonce and salt

{
  r: "fd1.session.login",
  data: {
    nonce: "abcdef12345",
    salt1: "na8f9$9hb",
    salt2: "9gb76"
  }
}

Combine the nonce with sha-256 of (salt + password) and transmit the result, using the logic

  1. Combine salts and password, then calculate the SHA-256 of that
    set temp = String(salt1) + String(password) + String(salt2)
    set encoded = crypto.subtle.digest("SHA-256", temp)
    set b64 = MakeBase64(encoded)
  2. Combine nonce and sha-256 base64 value
    let combined = String(nonce) + String(b64)
  3. Calculate SHA-256 of that value
    let sha256 = crypto.subtle.digest("SHA-256", combined)
    NB. The actual required steps are more complex. See https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest for worked examples
  4. Convert the SHA-256 result to base64, and transmit that.
{
  a: "fd1.session.login",
  v: {
    method: "user/pass",
    sha256: "28fe9283ba09c7e"
  }
}

A Proof of key exchange. Each end must have been initialised with a unique key. ie both ends have the same key. These keys are typically 1Mb or more in size.

Step 1. Request a server supplied nonce

{
  a: "fd1.session.login",
  v: {
    method: "proofofkey",
    dateutc: "2024-05-02 06:07:08"
  }
}

Wait for server response containing the nonce

{
  r: "fd1.session.login",
  data: {
    nonce: "abcdef12345"
  }
}

Calculate an offset into the preshared key

{
  a: "fd1.session.login",
  v: {
    method: "user/pass",
    sha256: "28fe9283ba09c7e"
  }
}

fd1.session.set_option

Change individual options on the session.

Option NameDescriptonExample
tz Sets the Timezone offset being used by the caller. The server may need to store dates in the local users time and needs to know the timezone in order to calculate this.

The value is derived from the Javascript (new Date()).getTimezoneOffset()

tz: -360
localtime Sets the current localtime in the browser. Be very careful to send local time, not UTC time.

The value is derived from the Javascript

let myDate = new Date();
let localtime = myDate.getFullYear() + "-"
    + (myDate.getMonth() + 1) + "-" 
    + myDate.getDate() + " " 
    + myDate.getHours() + ":" 
    + myDate.getMinutes() + ":" 
    + myDate.getSeconds() + "." 
    + myDate.getMilliseconds()
                                    

localtime: "2024-01-02 13:45:22.972"
apikey
qr
These options cannot be set using set_option, they can only be specified as part of fd1.session.login

Example

When using SalesBuilder, reply with partial sale details

{
  a: "fd1.session.set_option",
  k: "jafj459385hggdg39vgcg53038qQQ8",
  v: {
    salesbuilder: "reply-brief-sale"
  }
}