Authentication

The Luffa API uses API keys to authenticate requests. You can generate and manage your API keys from your dashboard.

API Keys

API keys are the primary method for authenticating with the Luffa API. Include your API key in the Authorization header of each request.

Getting Your API Key

  1. Log in to your Luffa dashboard
  2. Navigate to Settings > API Keys
  3. Click Create New API Key
  4. Give your key a descriptive name
  5. Copy the generated key (you won't be able to see it again)

Using API Keys

Include your API key in the Authorization header:

curl -H "Authorization: Bearer luffa_sk_1234567890abcdef" \
  https://api.luffa.dev/v1/documents
const response = await fetch('https://api.luffa.dev/v1/documents', {
  headers: {
    'Authorization': 'Bearer luffa_sk_1234567890abcdef',
    'Content-Type': 'application/json'
  }
})
import requests

headers = {
    'Authorization': 'Bearer luffa_sk_1234567890abcdef',
    'Content-Type': 'application/json'
}

response = requests.get('https://api.luffa.dev/v1/documents', headers=headers)

API Key Types

Secret Keys (luffa_sk_)

  • Use case: Server-side applications
  • Permissions: Full access to your account
  • Security: Never expose in client-side code

Public Keys (luffa_pk_)

  • Use case: Client-side applications
  • Permissions: Read-only access to public resources
  • Security: Safe to include in frontend code

Rate Limiting

API keys are subject to rate limits based on your plan:

PlanRequests per HourBurst Limit
Free1,000100
Pro10,0001,000
EnterpriseCustomCustom

Rate limit headers are included in all responses:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1640995200
X-RateLimit-Retry-After: 3600

Error Responses

401 Unauthorized

{
  "error": {
    "type": "authentication_error",
    "code": "invalid_api_key",
    "message": "Invalid API key provided",
    "docs_url": "https://docs.luffa.dev/api/authentication"
  }
}

403 Forbidden

{
  "error": {
    "type": "permission_error", 
    "code": "insufficient_permissions",
    "message": "API key does not have permission for this operation",
    "docs_url": "https://docs.luffa.dev/api/authentication"
  }
}

429 Rate Limited

{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limit_exceeded", 
    "message": "API rate limit exceeded",
    "retry_after": 3600,
    "docs_url": "https://docs.luffa.dev/api/authentication"
  }
}

Best Practices

Key Management

DO:

  • ✅ Store API keys as environment variables
  • ✅ Use different keys for different environments
  • ✅ Rotate keys regularly (quarterly recommended)
  • ✅ Delete unused keys immediately
  • ✅ Use minimal permissions for each key

DON'T:

  • ❌ Commit API keys to version control
  • ❌ Share keys via email or chat
  • ❌ Use production keys in development
  • ❌ Log API keys in application logs
  • ❌ Hardcode keys in client-side code

Environment Variables

# .env.local
LUFFA_API_KEY=luffa_sk_1234567890abcdef
LUFFA_API_BASE_URL=https://api.luffa.dev/v1

# For different environments
LUFFA_API_KEY_DEV=luffa_sk_dev_1234567890abcdef
LUFFA_API_KEY_PROD=luffa_sk_prod_1234567890abcdef

Error Handling

async function callLuffaAPI(endpoint, options = {}) {
  try {
    const response = await fetch(`https://api.luffa.dev/v1${endpoint}`, {
      headers: {
        'Authorization': `Bearer ${process.env.LUFFA_API_KEY}`,
        'Content-Type': 'application/json',
        ...options.headers
      },
      ...options
    })

    if (!response.ok) {
      const error = await response.json()
      throw new LuffaAPIError(error, response.status)
    }

    return await response.json()
  } catch (error) {
    if (error.status === 401) {
      // Handle authentication error
      console.error('Invalid API key')
    } else if (error.status === 429) {
      // Handle rate limiting
      const retryAfter = error.headers.get('retry-after')
      console.error(`Rate limited. Retry after ${retryAfter} seconds`)
    }
    throw error
  }
}

OAuth 2.0 (Enterprise)

For enterprise customers, Luffa supports OAuth 2.0 for user authentication.

Authorization Code Flow

  1. Redirect to Authorization
https://auth.luffa.dev/oauth/authorize?
  client_id=your_client_id&
  redirect_uri=https://yourapp.com/callback&
  scope=read:documents+write:documents&
  response_type=code&
  state=random_state_string
  1. Exchange Code for Token
curl -X POST https://auth.luffa.dev/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "client_id=your_client_id" \
  -d "client_secret=your_client_secret" \
  -d "code=auth_code_from_callback" \
  -d "redirect_uri=https://yourapp.com/callback"
  1. Use Access Token
curl -H "Authorization: Bearer oauth_access_token" \
  https://api.luffa.dev/v1/user/documents

Webhooks Authentication

Webhooks include a signature header for verification:

const crypto = require('crypto')

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex')
    
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  )
}

// Express.js example
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-luffa-signature']
  const isValid = verifyWebhookSignature(req.body, signature, process.env.WEBHOOK_SECRET)
  
  if (!isValid) {
    return res.status(401).send('Invalid signature')
  }
  
  // Process webhook
  res.status(200).send('OK')
})

Testing Authentication

Use our test endpoints to verify your authentication setup:

# Test your API key
curl -H "Authorization: Bearer YOUR_API_KEY" \
  https://api.luffa.dev/v1/auth/test

# Expected response
{
  "authenticated": true,
  "key_id": "key_1234567890",
  "permissions": ["read:documents", "write:documents"],
  "rate_limit": {
    "limit": 1000,
    "remaining": 999,
    "reset": 1640995200
  }
}

Need Help?

Was this page helpful?