{ data, error } returns, auto-pagination, and built-in retry logic.
Installation
npm install @nawalabs/sdk
Quick start
import { Nawa } from '@nawalabs/sdk'
const nawa = new Nawa({
apiKey: process.env.NAWA_API_KEY // nawa_live_sk_xxx or nawa_test_sk_xxx
})
// Classify an Arabic comment
const { data, error } = await nawa.classify({
text: 'ما شاء الله عليك، محتوى رهيب!',
platform: 'youtube'
})
if (error) {
console.error(error.type, error.message)
} else {
console.log(data.intent) // "praise"
console.log(data.dialect) // "gulf"
console.log(data.sentiment) // "positive"
}
The SDK uses
{ data, error } returns instead of throwing exceptions. This makes error handling explicit and avoids uncaught promise rejections.Classify comments
const { data, error } = await nawa.classify({
text: 'متى الجزء الثاني؟',
platform: 'youtube',
channelId: 'ch_123',
metadata: { videoId: 'vid_abc' }
})
if (data) {
console.log(data.intent) // "question"
console.log(data.dialect) // "gulf"
console.log(data.dialect_confidence) // 0.95
console.log(data.cached) // false
}
Rubric classification
const { data, error } = await nawa.rubric.classify({
text: 'وين الترجمة العربية؟',
rubric: {
categories: ['translation_request', 'technical_issue', 'content_feedback'],
descriptions: {
translation_request: 'User wants subtitles or translation',
technical_issue: 'Audio/video problems',
content_feedback: 'Feedback on content quality'
}
}
})
if (data) {
console.log(data.category) // "translation_request"
console.log(data.scores) // { translation_request: 0.94, ... }
}
Generate replies
const { data, error } = await nawa.comments.reply('cmt_abc123', {
tone: 'friendly',
context: 'Tech review channel'
})
if (data) {
console.log(data.reply_text) // "إن شاء الله الجزء الثاني قريب!"
console.log(data.reply_dialect) // "gulf"
}
List comments with auto-pagination
// Single page
const { data, error } = await nawa.comments.list({
platform: 'youtube',
intent: 'question',
limit: 25
})
// Auto-pagination (async iterator)
for await (const comment of nawa.comments.list({ platform: 'youtube' })) {
console.log(comment.text, comment.intent)
}
Submit feedback
const { data, error } = await nawa.feedback.submit({
requestId: 'req_abc123def456',
field: 'dialect',
expectedValue: 'levantine',
comment: 'This is Lebanese Arabic'
})
Webhook signature verification
import { Nawa } from '@nawalabs/sdk'
const isValid = Nawa.webhooks.verify({
payload: requestBody,
signature: headers['x-nawa-signature'],
timestamp: headers['x-nawa-timestamp'],
secret: process.env.NAWA_WEBHOOK_SECRET
})
Error handling
The SDK provides typed errors for each error category:import { Nawa, NawaAuthError, NawaRateLimitError, NawaCreditsError } from '@nawalabs/sdk'
const { data, error } = await nawa.classify({ text: '...', platform: 'youtube' })
if (error) {
if (error instanceof NawaAuthError) {
// Invalid, expired, or revoked API key
console.error('Auth error:', error.code) // "invalid_api_key"
} else if (error instanceof NawaRateLimitError) {
// Rate limit exceeded - use error.retryAfter
console.log(`Retry after ${error.retryAfter}ms`)
} else if (error instanceof NawaCreditsError) {
// Insufficient credits
console.error('Buy credits:', error.suggestedAction)
} else {
// Server error - safe to retry
console.error('API error:', error.message)
}
}
Configuration
const nawa = new Nawa({
apiKey: process.env.NAWA_API_KEY,
// Retry configuration
maxRetries: 3, // Default: 3
retryDelay: 1000, // Base delay in ms. Default: 1000
retryBackoff: 'exponential', // "exponential" | "linear" | "none"
// Timeout
timeout: 30_000, // Request timeout in ms. Default: 30000
// Base URL override (for testing)
baseUrl: 'https://api.trynawa.com' // Default
})