FD1 Client Protocol
 
Library Developer Home FD1 Client Protocol Home Concepts Reading Data Writing Data Protocol Defined Servers Connect & Authenticate Proxies & Tunnels
Webhooks & Firehoses 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 Get Attribute 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 PosGreen 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 Webhooks & Firehoses

Fieldpine provides options to capture events in near realtime. When an event is fired, a message is sent to your endpoint containing some level of detail

  • Webhook Static registered URL Fieldpine sends to when events happen.
    • Fieldpine provides limited retry if your server is down
    • Suitable for low volume changes. As a general indication, Fieldpine dont permit webhooks for events that occur more than once every 30 seconds
    • Not currently generally available.
  • Firehose Receives objects over a websocket as events happen
    • Suitable for high volume. As an indication, up to around 10,000 events/second
    • Retry depends on the event. Data style events (eg edit customer) can be restarted, but memory style events (freezer temperature changed) cannot
  • Doorbell A doorbell URL is one that can be pinged, but does not explicitly require authorisation or Api Keys. Typically an external server 'rings a dorrbell' to say 'I have something for you', without passing any information of a sensitive nature. Doorbells do not respond with any data, and in fact can simply return 404 errors if they wish.

    For example, Fieldpine servers may ring a retailers doorbell when new data arrives. Fieldpine can call the retailer, but does not require any centralised Api Keys. Typically the receiver of a doorbell will schedule a poll operation.

Registering a Firehose

A firehose instructs the server to send all events or changes to you so long as the websocket is open. Firehose messages are only sent over websockets. You may open multiple firehoses over the same websocket. One websocket can have multiple different firehoses active. Avoid opening a seperate websocket for individual firehoses as websocket network connections are a finite resource.

Send a registration packet as shown over your websocket

{
    "a": "fd1.firehose.open_firehose",
    "rq": ... your request id ...
    "v": {
        "event": ... event name to subscribe ...
    }
}

Arguments

  • a Endpoint Address. Constant, required.
  • rq Request Id. Your request id. This value is returned in every firehose message sent to you in the "rp" field
  • v.event A single event to subscribe too. See list below

Messages Generic Format

{
    "rp": ....      // Original "rq" that requested the webhook or firehose event
    "sc": ... data content type
    "rve": NNNN  // timestamp for this record
    "data": {
        // Event specific data
    }
}

Example

Request a firehose of any customer changes

{
    "a": "fd1.firehose.open_firehose",
    "rq": "MY-customer-changed",
    "v": {
        "event": "pos.customers.change"
    }
}

Server will start sending customer changes as they occur

{"rp":"MY-customer-changed","data": { "id": "abc13432", "action", "E"}}
{"rp":"MY-customer-changed","data": { "id": "JSH82232", "action", "I"}}
{"rp":"MY-customer-changed","data": { "id": "K9wh394s", "action", "E"}}

Lets request product changes too

{
    "a": "fd1.firehose.open_firehose",
    "rq": "MY-product-1234",
    "v": {
        "event": "pos.product.change"
    }
}

Server will start sending both as they occur. Note how the "rp" field is your request value, and also the "sc" field changes

{"rp":"MY-customer-changed","v": { "id": "acv82s", "action", "E"}}
{"rp":"MY-product-1234","v": { "id": "kso92", "action", "E"}}
{"rp":"MY-customer-changed","v": { "id": "znzj2738", "action", "E"}}

Tips for Receiving

Firehoses are technically capable of sending many thousands of events per second and how you handle those messages is important. If the server detects you are too slow handling the communication; it can and will revoke sending to you.

  • Don't assume "my computers big enough". Size is not important, it is how you use it
  • Don't try and process a message inside your message receive loop.
  • Do create a "recevied queue" and put message in there
    // Thread reading websocket
    function FirehoseRead(x) {
        message x;
        while (WaitForNewMessage(x)) {
            LockReceivedQueue();
            AddToReceivedQueue(x);
            ReleaseReceivedLock();
    
            SetEvent(MessageReceived);      <<-- Done after lock released
        }
    }
    
    // Worker thread
    function ProcessFirehose() {
        while (forever) {
            LockReceivedQueue();
            if (GetFromReceiveQueue(...)) {
                ReleaseReceivedLock();      <<-- Important
                // Handle message, write to your database etc
            } else {
                ReleaseReceivedLock();
                WaitForEvent(MessageReceived);
            }
        }
    }
    
  • The upper bound of messages is the total bandwidth of your network connecton to the firehose server. If you have a 1Gbit network connecion, then you can roughly expect to receive a maximum of 100Mbytes/second. If a firehose packet averages 500 bytes, then you will receive a maximum of 200,000 packets per second. If you are traversing the internet though, then all components between must be capable of this sustained load.
    Firehose servers do not require confirmation of messages. They also pump messages as soon as practical (unless you have specifically requested slowing)

Restartable Firehoses

A restartable firehose is one that can restart from a given point and resend all1 messages.

To request a firehose restart, supply a "dv" value in your initial request

{
    "a": "fd1.firehose.open_firehose",
    "rq": "some-id",
    "dv": 2024031213004590422,      // <-- Restart timestamp
    "v": {
        "event": "pos.customers.change"
    }
}
                

1 "all" for restartable firehoses means all possible. Some events are transient in nature and cannot be resent if missed.

Event Names

NameDescriptionWhere
pos.customer.changeA customer record is editted, created, deleted. A direct change to a customer recordGds
pos.customer.change.any Anything relating to a single customer changes. This can be record edit (pos.customers.change) or related items such as email/text message received, new sale. Gds
salesbuilder.changeAn active sale has changed. An active sale is one still being created, or worked withPosGreen
debugscope.XYZ Diagnostic channels to Fieldpine applications. These are advanced firehoses and not available to most callers.
debugscope.siteissueSent as site level configuration issues detectedPosGreen
debugscope.exceptionSent for code level exceptions. Can be serious or trivial exceptionsPosGreen
debugscope.sitetraceSends a brief trace of more user level descriptions without heavy technical detailPosGreen
debugscope.poscommandSent as PosCommands evaluatedPosGreen
debugscope.dbstorageSent as database layer interacted withPosGreen
debugscope.funccallSends data about individual function being invoked. Requires additional setupPosGreen
debugscope.saleSent as sale type objects are alteredPosGreen
debugscope.settingsSent for each setting read/writePosGreen
debugscope.everythingSend everything. Reserved for automated test toolsPosGreen
debugscope.traceSends classic "trace lines" consisting of unstructured messages from developersPosGreen
debugscope.active_posHistoricPosGreen
debugscope.p41HistoricPosGreen
debugscope.p1792HistoricPosGreen
debugscope.developerReserved for low level developers to send/receive random data while testingAny