Authentication
Secure your API requests and manage user authentication
Samva uses two authentication methods:
- API Keys for server-to-server communication
- Better Auth for dashboard and user authentication
Security First: All API requests must be authenticated. We use industry-standard security practices to protect your data.
API Key Authentication
Creating API Keys
- Log in to the Samva Dashboard
- Navigate to Developers → API Keys
- Click Create API Key
- Set permissions and expiry (optional)
- Copy the key immediately - it won't be shown again
Using API Keys
Include your API key in the Authorization header:
// TypeScript SDK
const client = new SamvaClient({
apiKey: 'sk_live_your_api_key_here'
});# REST API
curl -H "Authorization: Bearer sk_live_your_api_key_here" \
https://samva.app/api/v1/messagesAPI Key Types
| Type | Prefix | Usage | Rate Limits |
|---|---|---|---|
| Live | sk_live_ | Production use | Standard limits |
| Test | sk_test_ | Development & testing | Reduced limits |
| Restricted | sk_restricted_ | Limited permissions | Based on config |
Best Practices
Use Environment Variables
Never hardcode API keys in your source code
Rotate Keys Regularly
Update your API keys every 90 days
Use Restricted Keys
Create keys with minimal required permissions
Monitor Usage
Track API key usage in the dashboard
User Authentication (Better Auth)
Overview
The Samva Dashboard uses Better Auth with:
- Email/Password authentication
- Multi-factor authentication (MFA)
- Organization-based multi-tenancy
Sign Up Flow
// Sign up with email and password
const response = await fetch('/api/auth/signup', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'user@example.com',
password: 'secure_password',
name: 'John Doe',
organization: 'Acme Corp'
})
});
// Verify email
await fetch('/api/auth/verify-email', {
method: 'POST',
body: JSON.stringify({
token: 'verification_token_from_email'
})
});Login Flow
// Login with email/password
const response = await fetch('/api/auth/login', {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'user@example.com',
password: 'your_password'
})
});Session Management
// Check current session
const session = await fetch('/api/auth/session', {
credentials: 'include'
});
// Logout
await fetch('/api/auth/logout', {
method: 'POST',
credentials: 'include'
});Organization & Multi-Tenancy
Organization Structure
Each Samva account belongs to an organization:
interface Organization {
id: string;
name: string;
credits: number; // Prepaid credits
settings: {
default_sender_ids: Record<string, string>;
webhook_url?: string;
ip_whitelist?: string[];
};
}Team Management
// Invite team member
await client.organizations.inviteTeamMember({
email: 'colleague@example.com',
role: 'developer', // admin, developer, viewer
permissions: ['send_messages', 'view_analytics']
});
// Accept invitation
await client.organizations.acceptInvitation(invitationToken);Security Features
Rate Limiting
API requests are rate-limited per API key:
| Plan | Requests/Second | Requests/Hour | Requests/Day |
|---|---|---|---|
| Free | 10 | 1,000 | 10,000 |
| Starter | 50 | 10,000 | 100,000 |
| Business | 100 | 50,000 | 1,000,000 |
| Enterprise | Custom | Custom | Custom |
Rate limit headers in responses:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640995200IP Whitelisting
Restrict API access to specific IP addresses:
// Configure in dashboard or via API
await client.organizations.updateSettings({
ip_whitelist: [
'203.0.113.0/24',
'198.51.100.42'
]
});Webhook Signatures
Verify webhook authenticity:
import crypto from 'crypto';
function verifyWebhookSignature(
payload: string,
signature: string,
secret: string
): boolean {
const hmac = crypto.createHmac('sha256', secret);
const digest = hmac.update(payload).digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(digest)
);
}
// In your webhook handler
app.post('/webhooks/samva', (req, res) => {
const signature = req.headers['x-samva-signature'];
const isValid = verifyWebhookSignature(
JSON.stringify(req.body),
signature,
process.env.WEBHOOK_SECRET
);
if (!isValid) {
return res.status(401).send('Invalid signature');
}
// Process webhook...
});OAuth 2.0 (Coming Soon)
OAuth 2.0 support for third-party integrations:
// Authorization URL
const authUrl = `https://samva.app/api/oauth/authorize?
client_id=${CLIENT_ID}&
redirect_uri=${REDIRECT_URI}&
response_type=code&
scope=messages:send analytics:read`;
// Token exchange
const token = await fetch('https://samva.app/api/oauth/token', {
method: 'POST',
body: JSON.stringify({
grant_type: 'authorization_code',
code: authorizationCode,
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET
})
});Error Handling
Authentication Errors
| Error Code | Description | Solution |
|---|---|---|
401 | Invalid or missing API key | Check your API key |
403 | Insufficient permissions | Use a key with required permissions |
429 | Rate limit exceeded | Reduce request frequency |
498 | Token expired | Refresh your session |
Common Issues
Invalid API Key Format
{
"error": "INVALID_API_KEY",
"message": "API key must start with sk_live_ or sk_test_"
}Organization Not Found
{
"error": "ORG_NOT_FOUND",
"message": "No organization associated with this API key"
}