Resources / Field guide

Reading data back from inRiver into FileMaker

A one-way FileMaker → inRiver push almost always grows a phase two: pulling fields back — storefront IDs, image URLs, computed values — into FileMaker. Here's the read-back workflow that reuses your existing API layer, plus the query gotcha that quietly drops records if you're not careful.

Why read-back is its own job

If you've built the push side (see inRiver ↔ FileMaker integration patterns), you already have an APICall engine, auth, and the $$inRiver_* response globals. Read-back reuses all of it — no new HTTP plumbing. What's new is two things: finding the entities you care about, and parsing field values out of inRiver (your push code only ever wrote them).

The two-step read

inRiver separates "which entities" from "their data," so a read is two calls:

  1. Find with POST /query — filter by entity type and criteria, get back matching entity IDs.
  2. Fetch with POST entities:fetchdata — pass those IDs plus a fieldTypeIds filter to pull only the fields you need.

A thin orchestrator per entity type ties them together: query → paginate the fetch → write back into FileMaker.

The gotcha that drops records: query criteria are AND-combined. If you filter a single /query on two storefront fields at once, inRiver returns only entities that have both populated — silently missing any product with just one. The fix is to query each field separately and union the resulting entity IDs, rather than relying on one multi-field query.

Finding the entities

Query one storefront field at a time (a system criterion on LastModified keeps nightly runs incremental), then union the ID sets in FileMaker:

# inRiver_QueryEntities — one field at a time
# body: entity type + a "modified since" system criterion + ONE data criterion
Set Variable [ $body ; Value: JSONSetElement ( "{}" ;
    [ "systemCriteria[0].type"     ; "EntityTypeId"        ; JSONString ] ;
    [ "systemCriteria[0].value"    ; "Product"             ; JSONString ] ;
    [ "systemCriteria[0].operator" ; "Equal"               ; JSONString ] ;
    [ "dataCriteria[0].fieldTypeId"; $storefrontField      ; JSONString ] ;
    [ "dataCriteria[0].operator"   ; "IsNotEmpty"          ; JSONString ]
) ]
# POST /query via APICall → returns matching entity IDs
# Repeat per storefront field, then UNION the ID lists (dedupe).

Fetching only the fields you need

Batch the IDs (1000 per page is a sane ceiling) and request just the storefront fields:

# inRiver_FetchEntityData — entities:fetchdata with a field filter
Set Variable [ $body ; Value: JSONSetElement ( "{}" ;
    [ "entityIds"     ; $idArray         ; JSONRaw ] ;   # array of integers
    [ "objects"       ; "FieldValues"    ; JSONString ] ;
    [ "fieldTypeIds"  ; "ShopifyProductId,ShopifyItemId,ImageUrl" ; JSONString ]
) ]
# POST entities:fetchdata via APICall

Parsing field values (the new part)

The FieldValues shape is the one piece your push scripts never touched, so inspect a real response before trusting it. Walk the entity's fields array once, grabbing the key and the values you want in a single pass — and avoid leaning on a custom function that may not exist in the file:

# Loop the fields array with built-in steps only (no custom functions)
Set Variable [ $fields ; Value: JSONGetElement ( $entity ; "fields" ) ]
Set Variable [ $i ; Value: 0 ]
Loop
    Exit Loop If [ $i ≥ ValueCount ( JSONListKeys ( $fields ; "" ) ) ]
    Set Variable [ $fid ; Value: JSONGetElement ( $fields ; "[" & $i & "].fieldTypeId" ) ]
    Set Variable [ $val ; Value: JSONGetElement ( $fields ; "[" & $i & "].value" ) ]
    # stash $fid/$val for the write-back…
    Set Variable [ $i ; Value: $i + 1 ]
End Loop

Use an exact-match find for the write-back. When you locate the FileMaker record to update, a plain value is a begins-with word search — key 100 would match 1000 and 100A. Force a whole-field match with the == operator: Set Field By Name [ matchField ; "==" & $key ]. Keys containing @ * # ? ! = < > still need backslash-escaping.

Run it safely

  • Test tenant first. Inspect $$inRiver_Response after the first query and the first fetch before you trust the write-back — the parse logic is the one spot most likely to need a tweak for your tenant's field shape.
  • Confirm your key fields. Know the exact key field type ID for each entity type (e.g. the SKU field for Items) so the write-back matches the right records.
  • Cached IDs survive Test→Live copies if entity IDs were copied across, so you usually don't need to re-map.

Need a PIM and your app kept in sync both ways?

I build production inRiver/PIM integrations — push, read-back, and nightly sync — directly, no hand-offs. Tell me what needs to stay in step.

Work with me