Skip to content

API Calls - Overview ​

Choose the right API utility for your use case.

Decision Tree ​

Follow these steps:

  1. Are you calling the API inside a function/event handler?

    • âś… Yes → Use $apiFetch
    • ❌ No → Continue to step 2
  2. Is the data organization-specific? (Should it auto-refresh when user switches orgs?)

    • âś… Yes → Use useOrgApi
    • ❌ No → Use useApi

Quick Comparison ​

FeatureuseApiuseOrgApi$apiFetch
When to useComponent setup, reactive dataOrg-specific data, auto-refreshes on org changeEvent handlers, functions, form submissions
Returns{ data, error, pending, refresh }{ data, error, pending, refresh }Promise<T>
Reactive✅ Yes✅ Yes❌ No
Auto-refresh on org change❌ No✅ Yes❌ No
Type safetyâś… Fullâś… Fullâś… Full

Examples ​

useApi - General Data ​

typescript
// User data, auth, public data
const { data: user } = useApi('/api/v1/auth/me', { lazy: true })

useOrgApi - Organization Data ​

typescript
// Almost everything in /hr/:orgId routes
// Auto-refreshes when user switches organizations
const { data } = useOrgApi('/api/organizations/...', { lazy: true })

$apiFetch - Programmatic Calls ​

typescript
// Form submissions, delete actions, etc.
const { $apiFetch } = useGetApiFetch()

const handleSubmit = async () => {
  await $apiFetch('/api/organizations/employees', {
    method: 'post',
    body: formData
  })
}

Key Rules ​

Pro Tips

  1. Always use lazy: true with useApi/useOrgApi for better UX
  2. Use useOrgApi for org data - handles org switching automatically
  3. Use $apiFetch in event handlers - simpler and more direct
  4. Types are auto-generated - you get full autocomplete!

Never Do This

typescript
// ❌ Don't use useFetch or $fetch directly
const { data } = useFetch('/api/endpoint')
const data = await $fetch('/api/endpoint')

// âś… Always use our wrappers
const { data } = useApi('/api/endpoint', { lazy: true })
const data = await $apiFetch('/api/endpoint')

Deep Dives: