Skip to content
Developersskuflo.iov1Changelog

Record a scan

POST/v1/scanScan station tokenBase URL api.skuflo.io

The event is fixed by the station, never by the request.

Auth is a station token (st_...), which is locked to one event (produce, stock or dispatch): the request cannot choose it. Returns 200 with ok:true (outcome ok or duplicate) or 409 with ok:false and an outcome explaining why the scan was refused: not_found (barcode does not match a label), not_produced (stock/dispatch scanned before produce), already_dispatched, cancelled, voided (see replacement_barcode), location_required / bad_location (stock scans need a valid rack bay from location or the station's default), or test for the printed hardware test label, which never touches an order. A dispatch station loads onto its open load only (no_load without one) and refuses another retailer's piece with wrong_retailer; with unscan it takes a loaded piece back off (unloaded). Set client_scan_id from an offline client so a queued replay is only ever counted once.

Try it now

Body parameters#

NameTypeDescription
barcoderequiredstring, max 64The label barcode as your scanner reads it. Send it raw: control characters, symbology prefixes and our QR link are cleaned up for you.
locationoptionalstring, max 8Rack bay for stock stations, e.g. A3
client_scan_idoptionalstring, max 64Set by offline clients so replays count once
return_conditionoptionalstringStock stations, returned pieces: the condition it came back in. Send it after a return_condition_required answer.
One of "new", "needs_repair", "unrepairable"
return_noteoptionalstring, max 500Optional note on a returned piece, e.g. what needs repairing
unscanoptionalbooleanDispatch stations: take this loaded piece back off its load and back into stock (the loader pressed Unscan). Refused with not_loaded or load_closed.
unexpected_returnoptionalobjectLog a return for a loaded piece that has no open return (after an already_dispatched answer with can_log_return). Needs return_condition too.
reasonoptionalstring·
One of "damaged_in_transit", "faulty", "wrong_item", "changed_mind", "other"
geooptionalobjectThe device position (GPS) when the scan was made. Stored only for stations with record_location on, and only with a client_scan_id.
latrequirednumber·
lngrequirednumber·
accuracyoptionalnumber·
atoptionalintegerWhen the device took the fix, ms since 1970

Outcomes#

The response is always { ok, outcome, barcode, item, order, ... }.

OutcomeStatusMeaning
ok200Accepted. The piece moved to its next state.
duplicate200This exact scan already happened (same piece, same event), or a replayed client_scan_id.
test200The printed hardware test label. Nothing was touched: this just proves the scanner and the station can talk to each other.
not_found409The barcode does not match a label in this factory.
not_produced409A stock or dispatch scan arrived before the piece was ever produced.
already_dispatched409The piece has already been loaded and cannot move again. On a stock station, can_log_return: true means it has no open return: send it again with unexpected_return and return_condition to log one.
return_condition_required409A stock station scanned a loaded piece that is on an open return. Nothing is recorded yet: return names the return and suggested_bay a returns bay. Send the scan again (with a new client_scan_id) with return_condition.
return_received200The returned piece is received, with its condition and, if location was given, the returns bay. The retailer is emailed and return.received fires.
bad_condition409return_condition must be new, needs_repair or unrepairable.
cancelled409The order this piece belongs to was cancelled.
voided409This label was voided. The response field replacement_barcode names the piece that replaced it, if any.
location_required409A stock scan needs a rack bay: pass location, or set a default location on the station.
bad_location409The rack bay given does not exist, or is out of range for that rack.

Other errors#

StatusMeaning
401No token, or the token is not recognised.
402billing_required. Reading always works, but this is a write and stops once a trial ends or a plan is cancelled.
429More than 600 requests a minute. Wait retry-after seconds.