On this page:
2.1 The setup
2.2 Listing records
2.3 Filtering and selecting
2.4 Getting a single record
2.5 Creating records
2.6 Updating records
2.7 Working with related records
2.8 Exploring the schema
2.9 What’s next
9.3

2 Quick Tour🔗

This section gives you a taste of what working with bcnav looks like. Don’t worry about understanding every detail—we’ll cover everything properly in the tutorials that follow.

2.1 The setup🔗

A typical bcnav session starts by loading the library and configuring your connection. You’ll usually put your credentials in environment variables rather than in code:

;; #lang racket
 
(require bcnav
         bcnav/api/master-data
         bcnav/api/sales)
 
;; Configure connection parameters
(current-bc-tenant (getenv "BC_TENANT_ID"))
(current-bc-environment "Production")
(current-bc-company (getenv "BC_COMPANY_ID"))
(current-bc-client-id (getenv "BC_CLIENT_ID"))
(current-bc-client-secret (getenv "BC_CLIENT_SECRET"))
 
;; Authenticate
(bc-authenticate!)

Once authenticated, you’re ready to make API calls. The authentication token is stored in a parameter and automatically included in all requests.

2.2 Listing records🔗

Each BC entity has a -list function that returns a bc-result:

(customers-list)

In the REPL, you’ll see a compact summary (instead of potentially thousands of records):

#<bc-result: customers (42 records, ~125 KB)>

You can iterate over results directly with for, or use bc-result->list to convert to a list. Each record is a hash table:

;; Iterate directly
(for ([cust (customers-list)])
  (displayln (hash-ref cust 'displayName)))
 
;; Or convert to list for list operations
(define all (bc-result->list (customers-list)))

2.3 Filtering and selecting🔗

To get specific records, use the #:query argument with make-query:

;; Find customers whose name contains "Contoso"
(customers-list #:query (make-query
                          #:filter (contains 'displayName "Contoso")))
 
;; Get only specific fields to reduce response size
(customers-list #:query (make-query
                          #:select '(id displayName email)
                          #:top 5))

Filter expressions compose naturally. Find unblocked customers with "Ltd" in their name:

(customers-list #:query (make-query
                          #:filter (and: (eq 'blocked #f)
                                         (contains 'displayName "Ltd"))))

2.4 Getting a single record🔗

Use the -get function with an ID:

(customers-get "a1b2c3d4-e5f6-7890-abcd-ef1234567890")

This returns a single hash table with all the customer’s fields.

2.5 Creating records🔗

Use the -create function with a hash table of field values:

(customers-create
  (hasheq 'displayName "New Customer Inc"
          'email "hello@newcustomer.com"
          'type "Company"))

The function returns the created record, including its new id and any server-generated fields.

2.6 Updating records🔗

Use the -update function with the record ID and a hash of fields to change:

(customers-update "a1b2c3d4-..."
                  (hasheq 'email "updated@contoso.com"))

BC uses ETags for optimistic concurrency—if someone else modified the record since you read it, the update will fail. You can pass the ETag explicitly:

(define cust (customers-get "a1b2c3d4-..."))
(customers-update (hash-ref cust 'id)
                  (hasheq 'email "updated@contoso.com")
                  #:etag (hash-ref cust 'odata.etag))

2.7 Working with related records🔗

Many BC entities have relationships. Use #:expand to fetch related records in a single call:

;; Get sales orders with their line items
(sales-order-list #:query (make-query
                            #:filter (eq 'status "Open")
                            #:expand '(salesOrderLines)))

Each order in the result will have a 'salesOrderLines field containing a list of its lines.

2.8 Exploring the schema🔗

Not sure what fields are available? Use inspect with the entity struct value:

(inspect customers)

This displays a formatted summary of the entity’s properties and what you can expand:

╭────────────────────────────────────────────╮

│ customers (standard v2.0 API)              

╰────────────────────────────────────────────╯

Key: id

 

╭──────────────────┬───────────────────┬────────────────┬──────────╮

│ Field            │ OData Type        │ Racket Type    │ Nullable │

├──────────────────┼───────────────────┼────────────────┼──────────┤

│ id               │ Edm.Guid          │ string?        │ no       

│ number           │ Edm.String        │ string?        │ yes      

│ displayName      │ Edm.String        │ string?        │ yes      

│ type             │ Edm.String        │ string?        │ yes      

│ ...                                                           

╰──────────────────┴───────────────────┴────────────────┴──────────╯

For enum fields (like assemblyPolicy on items), inspect also shows the allowed values with their numeric codes, so you know exactly what values you can filter on.

You can also preview actual data. Use peek for a formatted table display:

(peek customers)      ;; First 5 records as a table
(peek customers 10)   ;; First 10 records

This displays something like:

╭────────────────────────────────────────────────────────────╮

│ customers (standard v2.0 API) - 5 records                  

╰────────────────────────────────────────────────────────────╯

╭──────────────────┬──────────┬───────────────────┬──────────╮

│ id               │ number   │ displayName       │ email    

├──────────────────┼──────────┼───────────────────┼──────────┤

│ a1b2c3d4-...     │ C00010   │ Contoso Ltd       │ info@... │

│ e5f6g7h8-...     │ C00020   │ Fabrikam Inc      │ sales@...│

│ ...                                                     

╰──────────────────┴──────────┴───────────────────┴──────────╯

Or use sample to get the raw data as a list of hash tables:

(sample customers)      ;; First 5 records as list
(sample customers 10)   ;; First 10 records

2.9 What’s next🔗

This tour showed the basic shape of working with bcnav. The following tutorials cover each topic in depth: