Create a new record:
# Inline JSON
bcli post customers --data '{"displayName": "New Customer", "email": "new@example.com"}'
# From file
bcli post customers --data @customer.jsonThe @ prefix reads JSON from a file. The response shows the created record.
Update an existing record by ID:
bcli patch customers "a1b2c3d4-..." --data '{"email": "updated@example.com"}'
# From file
bcli patch customers "a1b2c3d4-..." --data @update.jsonBC uses ETags to prevent conflicting updates. By default, bcli sends If-Match: * (overwrite regardless). To enforce concurrency:
# First, get the record and note its @odata.etag
bcli -f raw get customers "a1b2c3d4-..."
# Then patch with the specific ETag
bcli patch customers "a1b2c3d4-..." --data '{"email": "new@email.com"}' --etag 'W/"ABC123"'Delete a record by ID:
bcli delete customers "a1b2c3d4-..."ETags work the same way as PATCH:
bcli delete customers "a1b2c3d4-..." --etag 'W/"ABC123"'Preview write operations without executing. Works on post, patch, delete,
and attach upload. The output adapts to --format:
Human format (default): rich panel on stderr with the resolved URL, profile context, and the request body.
bcli --dry-run post customers --data '{"displayName": "Test"}'
# --dry-run: would POST customers
# URL: https://api.businesscentral.dynamics.com/.../api/v2.0/companies(<id>)/customers
# Profile: dev
# Env: Sandbox
# Company: <company-id>
# {
# "displayName": "Test"
# }Machine format (-f json / -f ndjson / -f raw): a single JSON envelope
on stdout that an agent can parse before deciding whether to proceed:
bcli --dry-run -f json post customers --data '{"displayName": "Test"}'{
"dry_run": true,
"method": "POST",
"endpoint": "customers",
"resolved_url": "https://api.businesscentral.dynamics.com/.../customers",
"profile": "dev",
"environment": "Sandbox",
"company_id": "<company-id>",
"body": {"displayName": "Test"}
}PATCH and DELETE envelopes also include record_id. attach upload adds
file_path, byte_size, parent_type, and parent_id. The envelope shape is
stable — agents can rely on the field names.
When the audit log is enabled (see Audit Log), each
dry-run is recorded with outcome: "dry_run" so the paper trail captures intent
even when no HTTP call fires.
For custom endpoints not in the registry:
bcli post warehouseEntries --publisher contoso --group logistics --version v2.0 \
--data '{"itemNumber": "1000", "quantity": 50, "locationCode": "WEST"}'