Barcode Scanning via REST API

Add barcode scanning to your system using a REST API. Orca Scan lets you collect barcode scan data from any iOS, Android, or Enterprise Scanner. No camera code. No device libraries. No platform fragmentation. Users scan barcodes using the Orca Scan app, and your system retrieves or updates that data via HTTP endpoints and webhooks. One REST API for all devices.

How to use the Barcode Scanning REST API

You can access the REST API using any programming language. To get started:

  1. Install the Orca Scan app on an iOS or Android device
  2. Open the app and create a new sheet
  3. Customise your data capture fields
  4. Login to the Orca Scan web app
  5. Go to Account Settings and copy your API key
  6. Launch the command line on your computer
  7. Use the endpoints below with your API key to access data

REST API Endpoints

You can think of a sheet as a mini-database with its own unique configuration. The following endpoints let you manage sheets, rows, fields, history, and user access.

Sheets

GET /sheets = get a list of sheets
# request
curl https://api.orcascan.com/v1/sheets -H "Authorization: Bearer API-KEY"
// response
{
  "data": [
    {
      "_id": "62a3188f098a6343fe0d9c1b",
      "name": "Public API Owned",
      "isOwner": true,
      "canAdmin": true,
      "canUpdate": true,
      "canDelete": true,
      "canExport": true
    },
    {
      "_id": "62a31e89098a6343fe0d9c1e",
      "name": "Public API Readonly",
      "isOwner": false,
      "canAdmin": false,
      "canUpdate": false,
      "canDelete": false,
      "canExport": false
    },
    {
      "_id": "62a32045098a6343fe0d9c1f",
      "name": "Public API Can Update",
      "isOwner": false,
      "canAdmin": false,
      "canUpdate": true,
      "canDelete": false,
      "canExport": false
    },
    {
      "_id": "62a32061098a6343fe0d9c22",
      "name": "Public API Can Delete",
      "isOwner": false,
      "canAdmin": false,
      "canUpdate": false,
      "canDelete": true,
      "canExport": false
    },
    {
      "_id": "62a32112098a6343fe0d9c25",
      "name": "Public API Can Export",
      "isOwner": false,
      "canAdmin": false,
      "canUpdate": false,
      "canDelete": false,
      "canExport": true
    },
    {
      "_id": "62a3214f098a6343fe0d9c2a",
      "name": "Public API Can Admin",
      "isOwner": false,
      "canAdmin": true,
      "canUpdate": true,
      "canDelete": true,
      "canExport": false
    }
  ]
}
GET /sheets/:sheetId/settings = get sheet settings
# request (replace :sheetId)
curl https://api.orcascan.com/v1/sheets/:sheetId/settings \
    -H "Authorization: Bearer API-KEY"
// response
{
  "data": {
    "allowPublicExport": true,
    "publicExportUrl": "https://api.orcascan.com/v1/sheets/sVVKYsnp-9b7Rl7i.json",
    "allowPublicEntry": false,
    "publicEntryUrl": "https://api.orcascan.com/v1/62a3188f098a6343fe0d9c1b",
    "allowWebHookIn": false,
    "webHookInUrl": "https://api.orcascan.com/v1/sheets/XbC5Xc1CMgv9wq-C",
    "lookupUrl": "",
    "validationUrl": "",
    "webHookOutUrl": "",
    "secret": "G4t3k33p3r!",
    "dateTimeFormat": "(DD/MM/YYYY HH:mm:ss) 01/12/2019 13:30:00"
  }
}
PUT /sheets/:sheetId/settings = update sheet settings
curl -X PUT \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer orca_aYUClq9tI0oxqKPfXwVHo3mVy7v" \
    -d '{ "allowPublicExport": true, "allowPublicEntry": true, "allowWebHookIn": true, "lookupUrl": "", "validationUrl": "", "webHookOutUrl": "", secret: "G4t3k33p3r!" }' \
    https://api.orcascan.com/v1/sheets/:sheetId/settings
PUT /sheets/:sheetId/clear = clear all rows in a sheet
# request (replace :sheetId)
curl -X PUT \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer API-KEY" \
    https://api.orcascan.com/v1/sheets/:sheetId/clear
POST /sheets = create a sheet
# request
curl -X POST \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer API-KEY" \
    -d '{ "name": "My things", "templateName": "Inventory" }' \
    https://api.orcascan.com/v1/sheets
// response
{
  "data": {
    "_id": "6664ff416518d60a3c1c700a",
    "name": "My things",
    "rows": 0
  }
}
PUT /sheets/:sheetId/rename = rename a sheet
# request (replace :sheetId)
curl -X PUT \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer orca_aYUClq9tI0oxqKPfXwVHo3mVy7v" \
    -d '{ "name": "New sheet name", "description": "Backup 27 May 2004" }' \
    https://api.orcascan.com/v1/sheets/:sheetId/rename
DELETE /sheets/:sheetId = delete a sheet
# request (replace :sheetId)
curl -X DELETE \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer API-KEY" \
    https://api.orcascan.com/v1/sheets/:sheetId

Rows

GET /sheets/:sheetId/rows = get all rows
# by default, it returns the field keys, to return the field titles pass `?withTitles=true`.
# request (replace :sheetId)
curl https://api.orcascan.com/v1/sheets/:sheetId/rows \ -H "Authorization: Bearer API-KEY"
// response
{
  "data": [
    {
      "_id": "62b8abeb1a3f8d11e2ad781e",
      "barcode": "6344554293308",
      "name": "Fantastic Cotton Gloves",
      "quantity": "20",
      "description": "Sit tenetur iusto error eum laboriosam laboriosam.",
      "date": "2017-01-01T18:38:17.000Z",
      "location": "52.4319404, 0.5114626"
    },
    {
      "_id": "62b8abeb1a3f8d11e2ad781f",
      "barcode": "8162055462301",
      "name": "Unbranded Frozen Table",
      "quantity": "71",
      "description": "Inventore aut rerum. Ea tempore error cupiditate",
      "date": "2017-01-14T04:10:16.000Z",
      "location": "51.6993409, 0.9225196"
    }
  ]
}
GET /sheets/:sheetId/rows/count = get row count
# request (replace :sheetId)
curl https://api.orcascan.com/v1/sheets/:sheetId/rows/count \ -H "Authorization: Bearer API-KEY"
// response
{
  "data": {
      "count": 100 // rows in your sheet
  }
}
GET /sheets/:sheetId/rows/:rowId = get a single row
# by default, it returns the field keys, to return the field titles pass `?withTitles=true`.
# request (replace :sheetId and :rowId)
curl https://api.orcascan.com/v1/sheets/:sheetId/rows/:rowId \
    -H "Authorization: Bearer API-KEY"
// response
{
  "data": {
    "_id": "62a322f13a2579cd32b66c14",
    "barcode": "barcode123456",
    "name": "Hello World"
  }
}
POST /sheets/:sheetId/rows = add row(s)
# if a barcode is not provided in the row data, it will be auto generated
#
# add a single row.
# by default, it returns the field keys, to return the field titles pass `?withTitles=true`.
# request (replace :sheetId)
curl -X POST \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer API-KEY" \
    -d '{ "barcode": "12345", "name": "Hello World", "photo": "base64..." }' \
    https://api.orcascan.com/v1/sheets/:sheetId/rows
// response
{
  "data": {
    "_id": "629d313d74e4a61bf1517d3a",
    "barcode": "12345",
    "name": "Hello World",
    "photo": "https://cdn.orca.storage/.../photo/jEIM9pSWdC2NG6HbmpebwA.jpg"
  }
}
# if a barcode is not provided in the row data, it will be auto generated
#
# by default, updates replace the entire row with the provided data. To update only specific fields while keeping the rest of the row unchanged, 
# include ?partial=true in the URL. This ensures that only the fields you provide are modified, while all other fields remain intact.
# i.e. https://api.orcascan.com/v1/sheets/:sheetId/rows?partial=true
#
# add multiple rows (if a row already exists, it will be updated)
# request (replace :sheetId)
curl -X POST \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer API-KEY" \
    -d '[ { "barcode": "1234", "name": "Hello World", "photo": "base64..." }, { "barcode": "5678", "name": "Hello Again", "photo": "base64..." } ]' \
    https://api.orcascan.com/v1/sheets/:sheetId/rows
// response
{
  "data": [
    {
      "_id": "669fc3b9d74909b0542638c1",
      "barcode": "1234",
      "name": "Hello World",
        "photo": "https://cdn.orca.storage/.../photo/jEIM9pSWdC2NG6HbmpebwA.jpg"
    },
    {
      "_id": "669fc3b9d74909b0542638c2",
      "barcode": "5678",
      "name": "Hello Again",
            "photo": "https://cdn.orca.storage/.../photo/jEIM9pSWdC2NG6HbmpebwB.jpg"
    }
  ]
}
PUT /sheets/:sheetId/rows/:rowId = update a single row
# by default, an update replaces the entire row with the provided data. To update only specific fields while keeping the rest of the row unchanged, 
# include ?partial=true in the URL. This ensures that only the fields you provide are modified, while all other fields remain intact.
# i.e. https://api.orcascan.com/v1/sheets/:sheetId/rows/:rowId?partial=true
#
# by default, it returns the field keys, to return the field titles pass `?withTitles=true`.
#
# request (replace :sheetId and :rowId)
curl -X PUT \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer API-KEY" \
    -d '{ "barcode": "789", "name": "Hello World", "photo": "base64..." }' \
    https://api.orcascan.com/v1/sheets/:sheetId/rows/:rowId
// response
{
  "data": {
    "_id": "629d313d74e4a61bf1517d3a",
    "barcode": "789",
    "name": "Hello World",
        "photo": "https://cdn.orca.storage/.../photo/jEIM9pSWdC2NG6HbmpebwA.jpg"
  }
}
PUT /sheets/:sheetId/rows = update multiple rows
# by default, updates replace the entire row with the provided data. To update only specific fields while keeping the rest of the row unchanged, 
# include ?partial=true in the URL. This ensures that only the fields you provide are modified, while all other fields remain intact.
# i.e. https://api.orcascan.com/v1/sheets/:sheetId/rows?partial=true
#
# by default, it returns the field keys, to return the field titles pass `?withTitles=true`.
#
# if a row does not exist, it will be added
# request (replace :sheetId)
curl -X PUT \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer API-KEY" \
    -d '[ { "barcode": "1234", "name": "Hello World", "photo": "base64..." }, { "barcode": "5678", "name": "Hello Again", "photo": "base64..." } ]' \
    https://api.orcascan.com/v1/sheets/:sheetId/rows
// response
{
  "data": [
    {
      "_id": "669fc3b9d74909b0542638c1",
      "barcode": "1234",
      "name": "Hello World",
        "photo": "https://cdn.orca.storage/.../photo/jEIM9pSWdC2NG6HbmpebwA.jpg"
    },
    {
      "_id": "669fc3b9d74909b0542638c2",
      "barcode": "5678",
      "name": "Hello Again",
            "photo": "https://cdn.orca.storage/.../photo/jEIM9pSWdC2NG6HbmpebwB.jpg"
    }
  ]
}
DELETE /sheets/:sheetId/rows/:rowId = delete a single row
# request (replace :sheetId and :rowId)
curl -X DELETE \
    -H "Authorization: Bearer API-KEY" \
    https://api.orcascan.com/v1/sheets/:sheetId/rows/:rowId
DELETE /sheets/:sheetId/rows = delete multiple rows
# request (replace :sheetId)
curl -X DELETE \
    -H "Authorization: Bearer API-KEY" \
    -d '[ rowId1, rowId2 ]' 
    https://api.orcascan.com/v1/sheets/:sheetId/rows

History

GET /sheets/:sheetId/history = get sheet history
# request (replace :sheetId)
curl https://api.orcascan.com/v1/sheets/:sheetId/history \
    -H "Authorization: Bearer API-KEY"
// response
{
  "data": [
    {
      "_id": "66678a4627b78f52140c12bc",
      "barcode": "clx9ljgms0000z0dr0fop94zq",
      "name": "new row",
      "quantity": 20,
      "_change": "add",
      "_changedBy": "public-api-user@orcascan.com",
      "_changedOn": "2024-06-10T23:20:38.704Z",
      "_changedUsing": "",
    },
    {
      "_id": "66678a4627b78f52140c12bd",
      "barcode": "clx9ljgms0000z0dr0fop94zq",
      "name": "updated row",
      "quantity": 99,
      "_change": "update",
      "_changedBy": "public-api-user@orcascan.com",
      "_changedOn": "2024-06-10T23:20:38.740Z",
      "_changedUsing": "",
    }
  ]
}
GET /sheets/:sheetId/:rowId/history = get row history
# request (replace :sheetId and :rowId)
curl https://api.orcascan.com/v1/sheets/:sheetId/:rowId/history \
    -H "Authorization: Bearer API-KEY"
// response
{
  "data": [
    {
      "_id": "66678a4627b78f52140c12bc",
      "barcode": "clx9ljgms0000z0dr0fop94zq",
      "name": "new row",
      "quantity": 20,
      "_change": "add",
      "_changedBy": "public-api-user@orcascan.com",
      "_changedOn": "2024-06-10T23:20:38.704Z",
      "_changedUsing": "",
    },
    {
      "_id": "66678a4627b78f52140c12bd",
      "barcode": "clx9ljgms0000z0dr0fop94zq",
      "name": "updated row",
      "quantity": 99,
      "_change": "update",
      "_changedBy": "public-api-user@orcascan.com",
      "_changedOn": "2024-06-10T23:20:38.740Z",
      "_changedUsing": "",
    }
  ]
}

Users

GET /sheets/:sheetId/users = get users
# request (replace :sheetId)
curl https://api.orcascan.com/v1/sheets/:sheetId/users -H "Authorization: Bearer API-KEY"
// response
{
  "data": [
    {
      "_id": "5f36ac26cdd51800ccdea10b",
      "email": "jenny@orcascan.com",
      "owner": false,
      "canUpdate": true,
      "canDelete": true,
      "canExport": true,
      "canAdmin": true
    }
  ]
}
POST /sheets/:sheetId/users = add a user to a sheet
# request (replace :sheetId)
curl -X POST \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer API-KEY" \
        -d '{ 
        "email": "new.user@example.com", 
        "canUpdate": true, 
        "canDelete": true, 
        "canExport": true, 
        "canAdmin": false 
      }' \
    https://api.orcascan.com/v1/sheets/:sheetId/users
// response
{
  "data": {
    "_id": "666b3d5f266e7bedc98a733f",
    "email": "new.user@example.com",
    "canUpdate": true,
    "canDelete": true,
    "canExport": true,
    "canAdmin": false
  }
}
PUT /sheets/:sheetId/users/:userId = update a user in a sheet
# request (replace :sheetId and :userId)
curl -X PUT \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer API-KEY" \
      -d '{ 
        "email": "new.user@example.com", 
        "canUpdate": true, 
        "canDelete": true, 
        "canExport": true, 
        "canAdmin": false 
      }' \
    https://api.orcascan.com/v1/sheets/:sheetId/users/:userId
// response
{
  "data": {
    "_id": "666b3d5f266e7bedc98a733f",
    "email": "new.user@example.com",
    "canUpdate": true,
    "canDelete": true,
    "canExport": true,
    "canAdmin": false
  }
}
DELETE /sheets/:sheetId/users/:userId = remove a user from a sheet
# request (replace :sheetId and :userId)
curl -X DELETE \
    -H "Authorization: Bearer API-KEY" \
    https://api.orcascan.com/v1/sheets/:sheetId/users/:userId

Webhooks

Register WebHooks to be notified when data changes (no need to poll).

GET /sheets/:sheetId/hook-events = get list of supported events
# request (replace :sheetId)
curl -H "Authorization: Bearer API-KEY" \
            https://api.orcascan.com/v1/sheets/:sheetId/hook-events
// response
{
  "data": [
    "rows:import:append",
    "rows:import:replace",
    "rows:add",
    "rows:update",
    "rows:delete",
    "columns:clear",
    "columns:update",
    "columns:delete",
    "columns:add",
    "sheet:clear",
    "sheet:delete",
    "sheet:settings:update",
    "*" // catch-all, fires for all events
  ]
}
GET /sheets/:sheetId/hooks = get all hooks on a sheet
# request (replace :sheetId)
curl -H "Authorization: Bearer API-KEY" \
            https://api.orcascan.com/v1/sheets/:sheetId/hooks
// response
{
  "data": [
    {
      "_id": "66b33ed93f843a1fa88836b6",
      "eventName": "rows:add",
      "sheetId": "62a3188f098a6343fe0d9c1b",
      "targetUrl": "https://example.com/add",
    },
    {
      "_id": "66b33ed93f843a1fa88836b7",
      "eventName": "rows:update",
      "sheetId": "62a3188f098a6343fe0d9c1b",
      "targetUrl": "https://example.com/update",
    },
  ]
}
GET /sheets/:sheetId/hooks/:hookId = get an existing hook
# request (replace :sheetId and :hookId)
curl -H "Authorization: Bearer API-KEY" \
            https://api.orcascan.com/v1/sheets/:sheetId/hooks/:hookId
// response
{
  "data": {
      "_id": "66b33ed93f843a1fa88836b6",
      "eventName": "rows:add",
      "sheetId": "62a3188f098a6343fe0d9c1b",
      "targetUrl": "https://example.com/add",
    }
}
POST /sheets/:sheetId/hooks = create a new hook
# request (replace :sheetId)
curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer API-KEY" \
  -d '{ "eventName": "rows:add", "targetUrl": "https://example.com/add" }' \
    https://api.orcascan.com/v1/sheets/:sheetId/hooks
// response
{
  "data": {
      "_id": "66b33ed93f843a1fa88836b6",
      "eventName": "rows:add",
      "sheetId": "62a3188f098a6343fe0d9c1b",
      "targetUrl": "https://example.com/add",
    }
}
PUT /sheets/:sheetId/hooks/:hookId = update an existing hook
# request (replace :sheetId and :hookId)
curl -X PUT \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer API-KEY" \
  -d '{ "eventName": "rows:update", "targetUrl": "https://example.com/update" }' \
    https://api.orcascan.com/v1/sheets/:sheetId/hooks/:hookId
// response
{
  "data": {
      "_id": "66b33ed93f843a1fa88836b6",
      "eventName": "rows:update",
      "sheetId": "62a3188f098a6343fe0d9c1b",
      "targetUrl": "https://example.com/update",
    }
}
DELETE /sheets/:sheetId/hooks/:hookId = delete an existing hook
# request (replace :sheetId and :hookId)
curl -X DELETE \
  -H "Authorization: Bearer API-KEY" \
	https://api.orcascan.com/v1/sheets/:sheetId/hooks/:hookId

Fields

Fields are the columns in an Orca Scan sheet.

GET /sheets/:sheetId/fields = get all fields in a sheet
# request (replace :sheetId)
curl https://api.orcascan.com/v1/sheets/:sheetId/fields -H "Authorization: Bearer API-KEY"
// response
{
    "data": [
        {
            "index": 0,
            "key": "barcode",
            "label": "Barcode",
            "type": "string",
            "required": true,
            "format": "text",
            "autofocus": false,
            "autoselect": false,
            "emptyOnEdit": false,
            "emptyOnScan": false,
            "hiddenWeb": false,
            "hiddenMobile": false,
            "readonlyWeb": false,
            "readonlyMobile": false,
            "useInMobileSearch": false,
            "useValueInList": true
        },
        {
            "index": 1,
            "key": "name",
            "label": "Name",
            "type": "string",
            "required": false,
            "format": "text",
            "autofocus": true,
            "autoselect": false,
            "default": "Orca",
            "emptyOnEdit": false,
            "emptyOnScan": false,
            "hiddenWeb": false,
            "hiddenMobile": false,
            "locked": true,
            "placeholder": "Enter the name here",
            "readonlyWeb": true,
            "readonlyMobile": false,
            "useInMobileSearch": false,
            "useValueInList": true
        },
        {
            "index": 2,
            "key": "location",
            "label": "Location",
            "type": "gps",
            "required": false,
            "format": "gps location (automatic)",
            "autofocus": false,
            "autoselect": false,
            "emptyOnEdit": false,
            "emptyOnScan": false,
            "hiddenWeb": false,
            "hiddenMobile": true,
            "readonlyWeb": false,
            "readonlyMobile": false,
            "useInMobileSearch": false,
            "useValueInList": false
        },
        {
            "index": 3,
            "key": "date",
            "label": "Date",
            "type": "datetime",
            "required": false,
            "format": "date time (automatic)",
            "autofocus": false,
            "autoselect": false,
            "emptyOnEdit": false,
            "emptyOnScan": false,
            "hiddenWeb": false,
            "hiddenMobile": true,
            "readonlyWeb": false,
            "readonlyMobile": false,
            "useInMobileSearch": false,
            "useValueInList": false
        }
    ]
}
POST /sheets/:sheetId/fields = add a new field to a sheet
# request (replace :sheetId)
curl -X POST \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer API-KEY" \
    -d '{ "label": "Category", "format": "drop-down list", "listOptions": ["Category 1", "Category 2"], "readonlyWeb": true }' \
    https://api.orcascan.com/v1/sheets/:sheetId/fields/
// response
{
    "data": {
        "key": "category",
        "label": "Category",
        "type": "string",
        "required": false,
        "format": "drop-down list",
        "autofocus": false,
        "autoselect": false,
        "emptyOnEdit": false,
        "emptyOnScan": false,
        "hiddenWeb": false,
        "hiddenMobile": false,
        "listOptions": [
            "Category 1",
            "Category 2"
        ],
        "readonlyWeb": true,
        "readonlyMobile": false,
        "useInMobileSearch": false,
        "useValueInList": false
    }
}
PUT /sheets/:sheetId/fields/:fieldKey = update an existing field
# request (replace :sheetId & :fieldKey)
curl -X PUT \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer API-KEY" \
    -d '{ "readonlyWeb": false, "hiddenWeb": false }' \
    https://api.orcascan.com/v1/sheets/:sheetId/fields/:fieldKey
// response
{
    "data": {
        "key": "name",
        "label": "Name",
        "type": "string",
        "required": false,
        "format": "text",
        "autofocus": true,
        "autoselect": false,
        "emptyOnEdit": false,
        "emptyOnScan": false,
        "hiddenWeb": false,
        "hiddenMobile": false,
        "readonlyWeb": false,
        "readonlyMobile": false,
        "useInMobileSearch": false,
        "useValueInList": true
    }
}
PUT /sheets/:sheetId/fields = upsert fields
# creates a field if it does not exist, otherwise updates it
curl -X PUT \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer orca_aYUClq9tI0oxqKPfXwVHo3mVy7v" \
    -d '[{ "label": "Quantity", "format": "number" }, { "label": "Notes", "format": "text", "required": true }]' \
    http://localhost:8181/sheets/62a3188f098a6343fe0d9c1b/fields
{
  "data": [
    {
      "key": "quantity",
      "label": "Quantity",
      "type": "integer",
      "required": false,
      "format": "number"
    },
    {
      "key": "notes",
      "label": "Notes",
      "type": "string",
      "required": true,
      "format": "text"
    }
  ]
}
DELETE /sheets/:sheetId/fields/:fieldKey = delete a field from a sheet
# request (replace :sheetId & :fieldKey)
curl -X DELETE \
    -H "Authorization: Bearer API-KEY" \
    https://api.orcascan.com/v1/sheets/:sheetId/fields/:fieldKey

Field options:

Name Type Description
key string Internal identifier (readonly)
label string Title of the field in the app
type string Data type
format string See Field formats below ↓
default any Default value for the field when empty
listOptions array If dropdown, options to present to users
multiSelect boolean If true, allows multiple selection
formula string Calculation for “formula” fields
currencyType string Currency code for “currency” fields, following the ISO 4217 standard (e.g. USD, EUR, GBP)
locked boolean Prevent users changing field properties
minLength integer Minimum number of characters allowed
maxLength integer Maximum number of characters allowed
minimum integer Minimum number allowed
maximum integer Maximum number allowed
placeholder string Guidance to the user when field is empty
prefix string If Unique ID, text before value
suffix string If Unique ID, text after value
length integer If Unique ID, total length of ID
required boolean User must provide a value (default: false)
autofocus boolean Auto select this field first (default: false)
autoselect boolean Highlight existing text on focus (default: false)
emptyOnEdit boolean Clear value when record edited (default: false)
emptyOnScan boolean Remove existing value on scan (default: false)
hiddenMobile boolean Hide the field on mobile (default: false)
hiddenWeb boolean Hide the field on web (default: false)
readonlyWeb boolean Prevent user input on web (default: false)
readonlyMobile boolean Prevent user input on mobile (default: false)
useInMobileSearch boolean Include value in mobile search (default: false)
useValueInList boolean Show field value in mobile list (default: false)
index integer Position of the field in the sheet

Field formats:

Format Description
text Plain text
barcode Barcode value populated on scan
number Stores a number (integer or decimal)
number (auto increase on scan) Number that auto increases on scan
number (auto decrease on scan) Number that auto decreases on scan
date Date field the user can set manually
date (automatic) Date field that auto sets on scan
date time Date and Time field the user can set manually
date time (automatic) Date and Time that auto sets on scan
time Time field the user can set manually
email Capture an email address
gps location User assigned GPS location
gps location (automatic) Auto assigned GPS location on scan
true/false True or False toggle field
currency Stores a monetary value
drop-down list List of options to present to users
formula Calculates the value of two or more fields
signature Captures a signature with date, time and location
unique id Generates a unique ID per record
photo Allows a user to add a photo
attachment Allows a user to upload a file
url Allows a user to enter a URL
created by Auto email of user who created the record
created date Auto date/time the record was created
last modified by Auto email of user who last modified the record
last modified date Auto date/time the record was last updated

Triggers

Triggers are per-sheet if-this-then-that rules that run when a row is scanned, added, or updated: if a condition matches, an action runs. Fields are referenced by their column title (e.g. Quantity), or (Any field) for a condition, and move row / copy row actions target another sheet by its name via toSheet. Actions such as run in the Orca Scan app as a user scans.

GET /sheets/:sheetId/triggers = get all triggers on a sheet
# request (replace :sheetId)
curl https://api.orcascan.com/v1/sheets/:sheetId/triggers \
    -H "Authorization: Bearer API-KEY"
// response
{
  "data": [
    {
      "_id": "66b33ed93f843a1fa88836b6",
      "name": "low stock alert",
      "conditionField": "Quantity",
      "conditionType": "is less than",
      "conditionValue": "5",
      "actionType": "notify me",
      "notifyMethod": "email",
      "notifyEmails": "ops@example.com",
      "enabled": true
    }
  ]
}
GET /sheets/:sheetId/triggers/:triggerId = get a single trigger
# request (replace :sheetId and :triggerId)
curl https://api.orcascan.com/v1/sheets/:sheetId/triggers/:triggerId \
    -H "Authorization: Bearer API-KEY"
// response
{
  "data": {
    "_id": "66b33ed93f843a1fa88836b6",
    "name": "low stock alert",
    "conditionField": "Quantity",
    "conditionType": "is less than",
    "conditionValue": "5",
    "actionType": "notify me",
    "notifyMethod": "email",
    "notifyEmails": "ops@example.com",
    "enabled": true
  }
}
POST /sheets/:sheetId/triggers = create a trigger
# required: name, conditionField, conditionType, actionType (trigger names must be unique per sheet)
#
# example: notify me when Quantity drops below 5
# request (replace :sheetId)
curl -X POST \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer API-KEY" \
    -d '{ "name": "low stock alert", "conditionField": "Quantity", "conditionType": "is less than", "conditionValue": "5", "actionType": "notify me", "notifyMethod": "email", "notifyEmails": "ops@example.com" }' \
    https://api.orcascan.com/v1/sheets/:sheetId/triggers
// response
{
  "data": {
    "_id": "66b33ed93f843a1fa88836b6",
    "name": "low stock alert",
    "conditionField": "Quantity",
    "conditionType": "is less than",
    "conditionValue": "5",
    "actionType": "notify me",
    "notifyMethod": "email",
    "notifyEmails": "ops@example.com",
    "enabled": true
  }
}
# example: move the row to another sheet (by name) when Quantity hits 0
# request (replace :sheetId)
curl -X POST \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer API-KEY" \
    -d '{ "name": "archive empties", "conditionField": "Quantity", "conditionType": "equals", "conditionValue": "0", "actionType": "move row", "toSheet": "Archive" }' \
    https://api.orcascan.com/v1/sheets/:sheetId/triggers
// response
{
  "data": {
    "_id": "66b33ed93f843a1fa88836c1",
    "name": "archive empties",
    "conditionField": "Quantity",
    "conditionType": "equals",
    "conditionValue": "0",
    "actionType": "move row",
    "toSheet": "Archive",
    "enabled": true
  }
}
PUT /sheets/:sheetId/triggers/:triggerId = update a trigger
# only the fields you send are changed, everything else is left as-is
# request (replace :sheetId and :triggerId)
curl -X PUT \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer API-KEY" \
    -d '{ "conditionValue": "10" }' \
    https://api.orcascan.com/v1/sheets/:sheetId/triggers/:triggerId
// response
{
  "data": {
    "_id": "66b33ed93f843a1fa88836b6",
    "name": "low stock alert",
    "conditionField": "Quantity",
    "conditionType": "is less than",
    "conditionValue": "10",
    "actionType": "notify me",
    "notifyMethod": "email",
    "notifyEmails": "ops@example.com",
    "enabled": true
  }
}
DELETE /sheets/:sheetId/triggers/:triggerId = delete a trigger
# request (replace :sheetId and :triggerId)
curl -X DELETE \
    -H "Authorization: Bearer API-KEY" \
    https://api.orcascan.com/v1/sheets/:sheetId/triggers/:triggerId

Trigger options:

Name Type Description
name string Trigger name, unique per sheet (required)
conditionField string Column title to test, or (Any field) (required)
conditionType string The comparison to run, see Condition types below ↓ (required)
conditionValue string Value the condition compares against (not needed for is empty / is not empty)
actionType string What happens when the condition matches, see Action types below ↓ (required)
actionField string Column title a field action targets (formula columns cannot be targeted)
actionValue string Value for the action, e.g. the value to set value
notifyMethod string For notify me: email, in app notification or in app dialog
notifyEmails string For notify me via email: comma-separated addresses (defaults to the sheet owner)
notifyType string For in-app notifications: success, warning or error
soundType string For play sound: success, warning or error
toSheet string For move row / copy row: the name of the destination sheet
enabled boolean Whether the trigger is active (default: true)

Condition types:

Condition Description
is empty Field has no value
is not empty Field has a value
contains Value contains the text
does not contain Value does not contain the text
starts with Value starts with the text
does not start with Value does not start with the text
ends with Value ends with the text
does not end with Value does not end with the text
equals Value matches exactly
does not equal Value does not match
is less than Value is less than a number
is greater than Value is greater than a number
matches regex Value matches a regular expression
does not match regex Value does not match a regular expression
contains GS1 AI Value contains a GS1 Application Identifier
exists in Value exists in another sheet
does not exist in Value does not exist in another sheet

Action types:

Action Description
notify me Send an email or in-app notification
move row Move the row to another sheet (toSheet)
copy row Copy the row to another sheet (toSheet)
show Show a field as the user scans
hide Hide a field as the user scans
set value Set a field’s value (actionField + actionValue)
clear value Clear a field’s value
set readonly Make a field read-only
clear readonly Make a field editable
set required Make a field required
clear required Make a field optional
play sound Play a success/warning/error sound

REST API Authentication

The Orca Scan REST API is secured using HTTPS and requires an API key with each request. Please note: you must have a Business subscription to use this feature.

Status Codes

The following HTTP status codes indicate the success or failure of a request:

Status Message Description
200 Ok Request successful
400 Bad request Your request is missing data
401 Unauthorized You do not have permission to access this resource
403 Forbidden You do not have permission to access this resource
404 Not found The requested URL was not found
409 Conflict The item you attempted to create already exists
500 Server Error Something unexpected happened
501 Not implemented The requested action is not supported
503 Service Unavailable Exceeded maximum number of requests per second

All HTTP errors include a JSON body structured as follows:

{
  "status": 400,
  "error": "Bad request",
  "message": "Invalid API key"
}

API Rate Limits

You can send up to 15 requests per second. If you exceed this limit, the API returns 429 Too Many Requests with a Retry-After header indicating how many seconds to wait before retrying.

To handle rate limits correctly:

This avoids unnecessary retries and keeps performance stable.

Is there an Open API specification?

Yes. You can find Orca Scan OpenAPI specifications here.

Barcode Scanning REST API FAQs

How do I upload a file?

Add a photo or attachment field to your sheet and provide the file content as a base64 string:

curl -X POST \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer API-KEY" \
    -d '{ "barcode": "12345", "photo": "base64..." }' \
    https://api.orcascan.com/v1/sheets/:sheetId/rows

What file types does the photo field support?

You can upload .jpg, .png, .gif, .bmp, .webp, .tiff and .svg files to a photo field.

What files types does the attachment field support?

You can upload .doc, .docx, .csv, .txt, .ppt, .pptx, .pdf, .xls, .xlsx and .mp4 files to an attachment field.

Does the API scrape barcodes?

The Orca Scan API doesn’t scrape barcodes – instead, it provides access to barcode data that’s captured through our mobile app. Your users scan barcodes using either iOS/Android devices or professional scanning hardware, and the API lets you retrieve and manage this scanned data in your applications.

Does the API return structured data?

Yes. Barcode scans are processed at capture time and delivered through the API as structured data. Field types and formats are applied before the data reaches your application, so you can consume it directly without additional parsing.

What barcode types does the Barcode Scanning API support?

Barcodes are captured using the Orca Scan app on a device, the Orca Scan app supports common 1D and 2D barcode formats, including QR codes and Code 128.

Can I extract data from barcodes before sending it to my API?

Yes. You can use Orca Variables to extract structured data from barcodes, such as GS1 elements, before the scan data is sent to your application via the Barcode Scanner REST API.

Do you have an SDK for the REST API?

Yes, orca-scan-node is an SDK for Node.js - if you need an SDK in another language, please chat to use live.

Barcode Scanning REST API questions?

As with everything at Orca Scan, our REST API will evolve based on your feedback. If you have any issues, suggestions, or something is not quite clear, chat with us live.

Ready to start scanning?