Getting Started
Prerequisites
Before you begin, ensure you have:
- A Finale Inventory account
- API key and secret (see Authentication)
Your First Query
Let's start with a simple query to fetch products from your inventory.
Query Structure
query {
productViewConnection(first: 5) {
edges {
node {
productId
description
}
}
pageInfo {
hasNextPage
endCursor
}
}
}Understanding the Query
productViewConnection: The query name for accessing productsfirst: 5: Fetch the first 5 productsedges: Wrapper for result items (Relay pattern)node: The actual product datapageInfo: Pagination metadata
Making the Request
curl -X POST "https://app.finaleinventory.com/youraccount/api/graphql" \
-H "Content-Type: application/json" \
-H "Authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
-d '{
"query": "query { productViewConnection(first: 5) { edges { node { productId description } } pageInfo { hasNextPage endCursor } } }"
}'Expected Response
{
"data": {
"productViewConnection": {
"edges": [
{
"node": {
"productId": "000-IMG-001",
"description": "Product with a random image"
}
},
{
"node": {
"productId": "000-IMG-002",
"description": "Product with random image"
}
}
],
"pageInfo": {
"hasNextPage": true,
"endCursor": "eyJpZHgiOjR9"
}
}
}
}Common Query Patterns
Fetching More Fields
Request additional fields by adding them to the node selection:
query {
productViewConnection(first: 5) {
edges {
node {
productId
description
skuList
unitsInStock
itemPrice
}
}
}
}Filtering Results
Apply filters to narrow down results:
query {
orderViewConnection(
first: 10
type: ["SALES_ORDER"]
status: ["OPEN", "IN_PROGRESS"]
) {
edges {
node {
orderId
orderDate
status
}
}
}
}Sorting Results
Order results by one or more fields:
query {
orderViewConnection(
first: 10
sort: [{ field: "orderDate", mode: "desc" }]
) {
edges {
node {
orderId
orderDate
}
}
}
}Paginating Through Results
Use cursors to fetch subsequent pages:
# First page
query {
productViewConnection(first: 50) {
edges {
node {
productId
description
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
# Next page (use endCursor from previous response)
query {
productViewConnection(
first: 50
after: "eyJpZHgiOjUwfQ=="
) {
edges {
node {
productId
description
}
}
pageInfo {
hasNextPage
endCursor
}
}
}Querying Related Data
Fetch related data in a single request:
query {
orderViewConnection(first: 10) {
edges {
node {
orderId
orderDate
customer {
name
email
}
origin {
locationId
name
}
}
}
}
}Using Variables
Make queries reusable with variables:
query GetOrders($pageSize: Int!, $orderType: [String!]) {
orderViewConnection(
first: $pageSize
type: $orderType
) {
edges {
node {
orderId
type
}
}
}
}Request body with variables:
{
"operationName": "GetOrders",
"variables": {
"pageSize": 20,
"orderType": ["SALES_ORDER", "RETURN_ORDER"]
},
"query": "query GetOrders($pageSize: Int!, $orderType: [String!]) { ... }"
}Available Collections
Common collections you can query:
productViewConnection- Products and inventoryorderViewConnection- Sales orders, purchase orders, transferslocationViewConnection- Warehouse and store locationspartyViewConnection- Customers and suppliersstockItemViewConnection- Stock item detailsinventoryTransactionViewConnection- Inventory movements
See the API Reference for a complete list.
Next Steps
Learn Core Concepts
- ViewConnections - Understand the connection pattern
- Pagination - Master cursor-based pagination
- Filtering - Learn filtering techniques
- Sorting - Sort your queries effectively
- Error Handling - Handle errors gracefully
Explore Reference Documentation
- API Reference - Browse all available collections
- Collection-specific docs (e.g., Order Reference)
Build Your Integration
- Design your data model based on available collections
- Write queries to fetch the data you need
- Implement pagination for large datasets
- Add error handling and retry logic
- Test with your Finale account data
Tips for Success
- Start small: Begin with simple queries and gradually add complexity
- Use GraphQL introspection: Query the schema to discover available fields
- Test in isolation: Use tools like GraphiQL or Postman to test queries
- Monitor performance: Watch query execution times and optimize as needed
- Handle errors gracefully: Always check for errors in responses
- Respect rate limits: Implement backoff strategies for production use
Example: Complete Integration Script
// Fetch all open sales orders with customer information
async function getOpenOrders() {
let hasNextPage = true
let cursor = null
const allOrders = []
// Create base64 encoded credentials from API key and secret
const credentials = Buffer.from(`${process.env.FINALE_KEY}:${process.env.FINALE_SECRET}`).toString('base64')
while (hasNextPage) {
const response = await fetch('https://app.finaleinventory.com/youraccount/api/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${credentials}`,
},
body: JSON.stringify({
operationName: 'GetOrders',
variables: {
first: 100,
after: cursor,
},
query: `
query GetOrders($first: Int!, $after: String) {
orderViewConnection(
first: $first
after: $after
type: ["SALES_ORDER"]
status: ["OPEN"]
sort: [{ field: "orderDate", mode: "desc" }]
) {
edges {
node {
orderId
orderDate
status
customer {
name
email
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
`,
}),
})
const data = await response.json()
if (data.errors) {
console.error('GraphQL errors:', data.errors)
break
}
const connection = data.data.orderViewConnection
allOrders.push(...connection.edges.map(e => e.node))
hasNextPage = connection.pageInfo.hasNextPage
cursor = connection.pageInfo.endCursor
}
return allOrders
}
// Usage
getOpenOrders()
.then(orders => {
console.log(`Fetched ${orders.length} open orders`)
console.log(orders)
})
.catch(error => {
console.error('Failed to fetch orders:', error)
})