Best practices
Learn how to efficiently consume BFG APIs.
This page outlines the recommended approach to consuming BFG APIs, ensuring clarity, reliability, and maintainability of client applications.
Using API design conventions
Response structures
Structure responses predictably. Each response should consistently use a root data key containing payload objects or arrays. Make sure to distinguish single-object responses from multiple-object responses.
For single resources
The data field contains an object.
{
"data": {
"id": 1,
"title": "Smithson MAP Policy 2024",
...
}
}For collections
The data field contains an array of objects. Use the links and meta objects to paginate.
{
"data": [ ... ],
"links": { ... },
"meta": { ... }
}Naming conventions
Use snake_case consistently for fields:
- Correct:
map_policy_type_id - Incorrect:
mapPolicyTypeID
Clearly named fields help developers intuitively understand the payload without frequent consultation of documentation.
Handling pagination
Use the standard meta and links fields to clearly convey pagination. For example, use links for navigation and meta to understand the pagination state:
"links": {
"first": "...",
"last": "...",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"per_page": 10,
"to": 7,
"total": 7
}Make sure navigation links (first, last, prev, next) correctly indicate available navigation options.
Note: Paginate using the page query parameter. Default page size is 10 unless otherwise documented.
Interpreting nullable and optional fields
Always expect fields such as contact_email, file_url, or contents to be nullable. If a value is not set, it will be explicitly returned as null.
"file_url": nullAvoid relying on missing fields—fields are never omitted.
Using feedback and error details
Use the message field to clearly communicate operational outcomes. For example, detail reasons for partial failures or skipped operations to enable straightforward debugging and corrective actions:
{
"data": {
"skipped_records": [
{
"upc": "082442935631",
"reason": "Product not found."
}
]
},
"message": "Product inventories updated successfully."
}Some responses may include a message field and a skipped_records array. Use these for diagnostics during batch operations.
Handling date and time
Timestamps are in the ISO 8601 format: YYYY-MM-DDTHH:MM:SS.sssZ. So follow the ISO 8601 format for date and time consistency and clarity:
"created_at": "2024-10-11T23:04:05.000000Z"Also, make sure to explicitly state the timezone (Z denotes UTC).
Some legacy fields, like created_at, may use a space delimiter (YYYY-MM-DD HH:MM:SS) so always parse accordingly.
Using boolean and status representations
Represent booleans explicitly with true or false. Avoid using strings for binary states:
"allow_add_to_cart": falseFor states requiring more than two values, prefer clear enumerations:
"allow_international_shipments": "REQUIRES_APPROVAL"Common status values for fields, like allow_free_shipping, might include the following:
YESNOREQUIRES_APPROVAL
Do not assume boolean values or numeric codes.
Specifying URLs and file links
Provide direct URLs clearly for downloadable resources:
"file_url": "https://bfg-atlas.s3.amazonaws.com/map.policies/files/1728773864-test.txt"You should always check if the URL is null before attempting access.
Working with nested data
Many resources include embedded nested JSON objects. Parse these as part of the response structure:
"map_advertising_pricing": {
"code": "MAP_MINIMUM",
"description": "MAP is Minimum Price"
}Using relationships and linked data
Fields such as company, retailer, or map_promotions often appear as nested objects. Always parse full relationships instead of relying solely on *_id fields:
"company": {
"name": "Ratke Ltd",
"account_id": "c4569d6c-0d9d-4a5b-9af6-13ec566d76a4"
}Examples of a well-structured client request
GET request
Here's an example of a GET request for the List Products API:
curl --request GET \
--url "https://api-sandbox.buyingfreedom.app/api/products\
?sort=title\
&page=1\
&page_size=10\
&include=company,map_promotions,inventories\
&include_inventory=true\
&filter[with_inventory]=true\
&filter[retailer_ids]=3,4\
&filter[inventory_sources]=store" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"POST request
Here's an example of a POST request for the Register a Store API:
curl --request POST \
--url "https://api-sandbox.buyingfreedom.app/api/store-locator/register" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data '{
"brand_account_id": "a7f8c122-3b9d-42cb-91d2-9f443fc94187",
"ffl_license_number": "183405029G20417",
"name": "Canyon Ridge Outfitters",
"logo": "https://example-cdn.com/logos/canyon-ridge-logo.png",
"phone": "3125550198",
"email": "[email protected]",
"website": "https://www.canyonridgegear.com",
"store_pickup": true,
"online_shopping": false,
"address_1": "742 Meadowbrook Way",
"address_2": "Suite B",
"address_3": null,
"city": "Fairmont",
"state": "WI",
"postal_code": "53716",
"country": "US"
}'PUT request
Here's an example of a PUT request for the Bulk Update Product Inventories:
curl --request PUT \
--url "https://api-sandbox.buyingfreedom.app/api/product-inventories" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data '{
"account_id": "d83a4e1f-4c0b-4e35-a2c5-22d2e962a1f4",
"product_inventories": [
{
"upc": "012345678905",
"quantity": 45
},
{
"upc": "987654321000",
"quantity": 120
},
{
"upc": "082442935631",
"quantity": 30
}
]
}'Updated 3 months ago