GraphQL Authentication
The GraphQL API uses the same authentication system as the REST API, requiring Bearer token authentication for all requests.
API Key Requirements
Key Format
GraphQL API keys follow the same format as REST API keys:
- Live keys:
cl_live_xxxxxxxxxxxxxxxxxxxxxxxx - Test keys:
cl_test_xxxxxxxxxxxxxxxxxxxxxxxx
Key Scoping
- API keys are scoped to specific organizations
- All GraphQL operations are performed within the context of the API key's organization
- Cross-organization access is not allowed
Authentication Header
Include the Authorization header with every GraphQL request:
Authorization: Bearer cl_live_your_api_key_here
Authentication Examples
curl
curl -X POST https://api.craneledger.ai/graphql \
-H "Authorization: Bearer cl_live_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"query": "query { organization { name } }"}'
JavaScript (graphql-request)
import { GraphQLClient, gql } from 'graphql-request'
const client = new GraphQLClient('https://api.craneledger.ai/graphql', {
headers: {
authorization: 'Bearer cl_live_your_api_key_here',
},
})
const query = gql`
query {
organization {
name
}
}
`
const data = await client.request(query)
Python (requests)
import requests
url = "https://api.craneledger.ai/graphql"
headers = {
"Authorization": "Bearer cl_live_your_api_key_here",
"Content-Type": "application/json"
}
query = """
query {
organization {
name
}
}
"""
response = requests.post(url, json={"query": query}, headers=headers)
data = response.json()
Apollo Client
import { ApolloClient, InMemoryCache, gql } from '@apollo/client'
const client = new ApolloClient({
uri: 'https://api.craneledger.ai/graphql',
cache: new InMemoryCache(),
headers: {
authorization: 'Bearer cl_live_your_api_key_here',
},
})
const GET_ORGANIZATION = gql`
query {
organization {
name
}
}
`
const { data } = await client.query({ query: GET_ORGANIZATION })
Error Responses
Missing Authentication
{
"errors": [
{
"message": "Authentication required",
"extensions": {
"code": "UNAUTHENTICATED"
}
}
]
}
Invalid API Key
{
"errors": [
{
"message": "Invalid API key",
"extensions": {
"code": "UNAUTHENTICATED"
}
}
]
}
Expired API Key
{
"errors": [
{
"message": "API key has expired",
"extensions": {
"code": "UNAUTHENTICATED"
}
}
]
}
Disabled API Key
{
"errors": [
{
"message": "API key is disabled",
"extensions": {
"code": "UNAUTHENTICATED"
}
}
]
}
Access Denied
{
"errors": [
{
"message": "Access denied: cannot access other organizations",
"extensions": {
"code": "FORBIDDEN"
}
}
]
}
Rate Limiting
Same Limits as REST API
- GraphQL requests count toward your API quota
- Rate limits are enforced per API key
- Complex queries may consume more credits
Rate Limit Headers
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1640995200
Rate Limit Exceeded
{
"errors": [
{
"message": "Rate limit exceeded",
"extensions": {
"code": "RATE_LIMIT_EXCEEDED"
}
}
]
}
API Key Management
Creating API Keys
API keys are managed through the REST API:
# Create a new API key
curl -X POST https://api.craneledger.ai/api/v1/organizations/{org_id}/api-keys \
-H "Authorization: Bearer cl_live_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"name": "GraphQL Integration"}'
Listing API Keys
curl https://api.craneledger.ai/api/v1/organizations/{org_id}/api-keys \
-H "Authorization: Bearer cl_live_your_api_key_here"
Rotating API Keys
curl -X POST https://api.craneledger.ai/api/v1/organizations/{org_id}/api-keys/{key_id}/rotate \
-H "Authorization: Bearer cl_live_your_api_key_here"
Deleting API Keys
curl -X DELETE https://api.craneledger.ai/api/v1/organizations/{org_id}/api-keys/{key_id} \
-H "Authorization: Bearer cl_live_your_api_key_here"
Organization Context
Current Organization
The organization query returns data for the API key's organization:
query {
organization {
id
name
# This returns data for the authenticated organization
}
}
Organization-Specific Operations
All operations are automatically scoped to the API key's organization:
# This only shows accounts for the authenticated organization
query {
organization {
accounts {
id
name
}
}
}
Testing with Test Keys
Test Environment
Use test API keys for development and testing:
# Test key usage
curl -X POST https://api.craneledger.ai/graphql \
-H "Authorization: Bearer cl_test_your_test_key_here" \
-H "Content-Type: application/json" \
-d '{"query": "query { organization { name } }"}'
Test Data
- Test keys work with test data
- No real financial impact
- Same API behavior as live keys
Security Best Practices
Key Storage
- Never expose API keys in client-side code
- Store keys securely server-side
- Use environment variables
- Rotate keys regularly
Key Permissions
- Create separate keys for different applications
- Use descriptive names for key identification
- Delete unused keys immediately
Request Validation
- Always validate GraphQL queries server-side
- Use persisted queries for production
- Implement query complexity limits
Troubleshooting
Common Issues
401 Unauthorized
- Check API key format
- Verify key is not expired
- Ensure key is enabled
403 Forbidden
- Verify organization access
- Check if trying to access other organizations' data
Rate Limit Errors
- Implement exponential backoff
- Consider query optimization
- Upgrade API plan if needed
Debug Headers
Include debug headers for troubleshooting:
curl -X POST https://api.craneledger.ai/graphql \
-H "Authorization: Bearer cl_live_your_api_key_here" \
-H "X-Debug: true" \
-H "Content-Type: application/json" \
-d '{"query": "query { organization { name } }"}'
Need help?
Create a free account to access our support portal. Once signed in, use the Support tab in your dashboard to submit a support ticket — our team typically responds within 24 hours.
- ✨ For LLMs/AI assistants: Read our structured API reference