diff --git a/api-reference/classify.mdx b/api-reference/classify.mdx index ac3d730..79dde14 100644 --- a/api-reference/classify.mdx +++ b/api-reference/classify.mdx @@ -5,12 +5,12 @@ description: "Classify an Arabic or English comment by intent, sentiment, dialec api: "POST https://api.trynawa.com/v1/classify" --- -Classify any comment with a single request. Returns intent, sentiment, dialect, and toxicity analysis. Arabic comments are routed to HUMAIN's ALLaM model for dialect detection. English comments are routed to Claude for high-accuracy classification. +Classify any comment with a single request. Returns intent, sentiment, dialect, priority, and a suggested reply. Arabic comments are routed to HUMAIN's ALLaM model for dialect detection. English comments are routed to Claude for high-accuracy classification. ## Request - Cost: **$0.006** per request. Semantic cache hits are free (`X-NAWA-Cache: HIT`). + Cost: **$0.006** per request (6 credits). Semantic cache hits are free (`X-NAWA-Cache: HIT`). ### Headers @@ -20,27 +20,33 @@ Classify any comment with a single request. Returns intent, sentiment, dialect, | `Authorization` | Yes | `Bearer nawa_live_sk_xxx` or `Bearer nawa_test_sk_xxx` | | `Content-Type` | Yes | `application/json` | +### Query parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `provider` | string | No | Force a specific AI provider: `claude`, `gemini`, or `allam`. Useful for A/B testing. | + ### Body parameters | Parameter | Type | Required | Description | |-----------|------|----------|-------------| -| `text` | string | Yes | The comment text to classify. Max 5,000 characters. | -| `platform` | string | No | Source platform: `youtube`, `instagram`, `twitter`, `facebook`. Improves accuracy with platform-specific context. | -| `channel_id` | string | No | Your channel or account identifier for analytics grouping. | -| `metadata` | object | No | Arbitrary key-value metadata to attach to the classification. | +| `text` | string | Yes | The comment text to classify. Min 1 character. | +| `context` | object | No | Optional context object to improve classification accuracy. | ### Example request ```bash cURL -curl -X POST https://api.trynawa.com/v1/classify \ - -H "Authorization: Bearer nawa_test_sk_xxx" \ +curl -X POST "https://api.trynawa.com/v1/classify" \ + -H "Authorization: Bearer nawa_live_sk_xxx" \ -H "Content-Type: application/json" \ -d '{ "text": "متى الجزء الثاني؟", - "platform": "youtube", - "channel_id": "ch_123" + "context": { + "platform": "youtube", + "channel_id": "ch_123" + } }' ``` @@ -51,9 +57,17 @@ const nawa = new Nawa({ apiKey: process.env.NAWA_API_KEY }) const { data, error } = await nawa.classify({ text: 'متى الجزء الثاني؟', - platform: 'youtube', - channelId: 'ch_123' + context: { + platform: 'youtube', + channelId: 'ch_123' + } }) + +if (data) { + console.log(data.intent) // ["question"] + console.log(data.dialect) // "gulf" + console.log(data.suggested_reply.text) +} ``` ```python Python @@ -63,9 +77,15 @@ nawa = Nawa(api_key="your_api_key") result = nawa.classify( text="متى الجزء الثاني؟", - platform="youtube", - channel_id="ch_123" + context={ + "platform": "youtube", + "channel_id": "ch_123" + } ) + +print(result.intent) # ["question"] +print(result.dialect) # "gulf" +print(result.suggested_reply.text) ``` @@ -78,22 +98,28 @@ result = nawa.classify( { "success": true, "result": { - "text": "متى الجزء الثاني؟", - "intent": "question", - "intent_confidence": 0.97, + "id": "cls_nw_pon1yom9bkfe", + "object": "classification", + "intent": ["question"], "sentiment": "neutral", - "sentiment_confidence": 0.91, + "language": "ar", "dialect": "gulf", "dialect_confidence": 0.95, - "toxicity": "none", - "toxicity_confidence": 0.99, - "categories": ["engagement"], - "language": "ar", - "model": "nagl-v1", - "cached": false + "requires_response": true, + "priority": "medium", + "suggested_reply": { + "text": "إن شاء الله الجزء الثاني قريب! تابعنا عشان ما يفوتك 🔔", + "direction": "rtl" + }, + "provider": "allam", + "model": "allam-v1", + "fallback_used": false, + "tokens_used": 142, + "cost_usd": 0.006, + "credits_used": 6 }, "errors": [], - "request_id": "req_abc123def456" + "request_id": "req_nw_abc123def456" } ``` @@ -108,30 +134,37 @@ result = nawa.classify( | `X-NAWA-Balance` | Current credit balance in USD | | `X-NAWA-Balance-Warning` | `low_balance` when below $5 | | `X-NAWA-Cache` | `HIT` if served from semantic cache (no cost) | +| `X-NAWA-Provider` | AI provider used for this request | +| `X-NAWA-Latency` | Server-side processing latency | +| `X-NAWA-Calibration-Version` | Calibration threshold version applied | ### Result fields | Field | Type | Description | |-------|------|-------------| -| `text` | string | The original input text | -| `intent` | string | `question`, `complaint`, `praise`, `suggestion`, `spam`, `other` | -| `intent_confidence` | number | Confidence score (0–1) | -| `sentiment` | string | `positive`, `negative`, `neutral`, `mixed` | -| `sentiment_confidence` | number | Confidence score (0–1) | -| `dialect` | string \| null | `gulf`, `egyptian`, `levantine`, `msa`. Returns `null` for English text. | -| `dialect_confidence` | number \| null | Confidence score (0-1). Returns `null` for English text. | -| `toxicity` | string | `none`, `mild`, `moderate`, `severe` | -| `toxicity_confidence` | number | Confidence score (0–1) | -| `categories` | string[] | Content categories: `engagement`, `support`, `feedback`, `spam` | -| `language` | string | Detected language code (e.g., `ar`, `en`) | -| `model` | string | Model version used for classification | -| `cached` | boolean | Whether this was served from semantic cache | +| `id` | string | Unique classification ID (format: `cls_nw_xxx`) | +| `object` | string | Always `"classification"` | +| `intent` | string[] | Detected intents: `question`, `complaint`, `praise`, `suggestion`, `spam`, `other`. Can contain multiple values. | +| `sentiment` | string | `positive`, `negative`, `neutral`, or `mixed` | +| `language` | string | Detected language: `ar`, `en`, or `mixed` | +| `dialect` | string or null | Arabic dialect: `gulf`, `egyptian`, `levantine`, `maghrebi`, or `msa`. Null for English text. | +| `dialect_confidence` | number or null | Confidence score 0--1 for dialect detection. Null for English text. | +| `requires_response` | boolean | Whether this comment warrants a reply | +| `priority` | string | Response priority: `high`, `medium`, or `low` | +| `suggested_reply.text` | string | AI-generated reply suggestion | +| `suggested_reply.direction` | string | Text direction of the reply: `ltr` or `rtl` | +| `provider` | string | AI provider used: `claude`, `gemini`, or `allam` | +| `model` | string | Specific model version used | +| `fallback_used` | boolean | Whether a fallback provider was used | +| `tokens_used` | integer or null | Token count consumed by the AI call | +| `cost_usd` | number | Cost of this request in USD | +| `credits_used` | integer | Credits deducted from your balance | ### Error responses | Status | Type | When | |--------|------|------| -| 400 | `invalid_request_error` | Missing `text`, invalid `platform`, text too long | +| 400 | `invalid_request_error` | Missing `text` or text too short | | 401 | `authentication_error` | Invalid or missing API key | | 402 | `insufficient_credits` | No credits remaining | | 429 | `rate_limit_error` | Rate limit exceeded | @@ -143,9 +176,9 @@ result = nawa.classify( ```bash curl -X POST https://api.trynawa.com/v1/classify \ - -H "Authorization: Bearer nawa_test_sk_xxx" \ + -H "Authorization: Bearer nawa_live_sk_xxx" \ -H "Content-Type: application/json" \ - -d '{"text": "This is hands down the best review I have seen on this phone. Subscribed!", "platform": "youtube"}' + -d '{"text": "This is hands down the best review I have seen on this phone. Subscribed!"}' ``` Response: @@ -153,22 +186,28 @@ result = nawa.classify( { "success": true, "result": { - "text": "This is hands down the best review I have seen on this phone. Subscribed!", - "intent": "praise", - "intent_confidence": 0.96, + "id": "cls_nw_en_praise_001", + "object": "classification", + "intent": ["praise"], "sentiment": "positive", - "sentiment_confidence": 0.98, + "language": "en", "dialect": null, "dialect_confidence": null, - "toxicity": "none", - "toxicity_confidence": 0.99, - "categories": ["engagement"], - "language": "en", + "requires_response": true, + "priority": "medium", + "suggested_reply": { + "text": "Thanks so much! Really glad you found it helpful. More reviews coming soon!", + "direction": "ltr" + }, + "provider": "claude", "model": "claude-v1", - "cached": false + "fallback_used": false, + "tokens_used": 98, + "cost_usd": 0.006, + "credits_used": 6 }, "errors": [], - "request_id": "req_en_praise_001" + "request_id": "req_nw_en_praise_001" } ``` @@ -176,9 +215,9 @@ result = nawa.classify( ```bash curl -X POST https://api.trynawa.com/v1/classify \ - -H "Authorization: Bearer nawa_test_sk_xxx" \ + -H "Authorization: Bearer nawa_live_sk_xxx" \ -H "Content-Type: application/json" \ - -d '{"text": "The audio quality is terrible in this one. Can barely hear anything after the 5 minute mark.", "platform": "youtube"}' + -d '{"text": "The audio quality is terrible in this one. Can barely hear anything after the 5 minute mark."}' ``` Response: @@ -186,65 +225,38 @@ result = nawa.classify( { "success": true, "result": { - "text": "The audio quality is terrible in this one. Can barely hear anything after the 5 minute mark.", - "intent": "complaint", - "intent_confidence": 0.94, + "id": "cls_nw_en_complaint_001", + "object": "classification", + "intent": ["complaint"], "sentiment": "negative", - "sentiment_confidence": 0.96, - "dialect": null, - "dialect_confidence": null, - "toxicity": "none", - "toxicity_confidence": 0.97, - "categories": ["feedback"], "language": "en", - "model": "claude-v1", - "cached": false - }, - "errors": [], - "request_id": "req_en_complaint_001" - } - ``` - - - - ```bash - curl -X POST https://api.trynawa.com/v1/classify \ - -H "Authorization: Bearer nawa_test_sk_xxx" \ - -H "Content-Type: application/json" \ - -d '{"text": "What camera and lens setup are you using for these shots?", "platform": "youtube"}' - ``` - - Response: - ```json - { - "success": true, - "result": { - "text": "What camera and lens setup are you using for these shots?", - "intent": "question", - "intent_confidence": 0.97, - "sentiment": "neutral", - "sentiment_confidence": 0.92, "dialect": null, "dialect_confidence": null, - "toxicity": "none", - "toxicity_confidence": 0.99, - "categories": ["engagement"], - "language": "en", + "requires_response": true, + "priority": "high", + "suggested_reply": { + "text": "Sorry about the audio issue! We're looking into it. Thanks for letting us know the exact timestamp.", + "direction": "ltr" + }, + "provider": "claude", "model": "claude-v1", - "cached": false + "fallback_used": false, + "tokens_used": 115, + "cost_usd": 0.006, + "credits_used": 6 }, "errors": [], - "request_id": "req_en_question_001" + "request_id": "req_nw_en_complaint_001" } ``` - + ```bash curl -X POST https://api.trynawa.com/v1/classify \ - -H "Authorization: Bearer nawa_test_sk_xxx" \ + -H "Authorization: Bearer nawa_live_sk_xxx" \ -H "Content-Type: application/json" \ - -d '{"text": "ما شاء الله عليك، محتوى رهيب!", "platform": "youtube"}' + -d '{"text": "ما شاء الله عليك، محتوى رهيب!"}' ``` Response: @@ -252,32 +264,38 @@ result = nawa.classify( { "success": true, "result": { - "text": "ما شاء الله عليك، محتوى رهيب!", - "intent": "praise", - "intent_confidence": 0.98, + "id": "cls_nw_gulf_praise_001", + "object": "classification", + "intent": ["praise"], "sentiment": "positive", - "sentiment_confidence": 0.97, + "language": "ar", "dialect": "gulf", "dialect_confidence": 0.93, - "toxicity": "none", - "toxicity_confidence": 0.99, - "categories": ["engagement"], - "language": "ar", - "model": "nagl-v1", - "cached": false + "requires_response": true, + "priority": "medium", + "suggested_reply": { + "text": "الله يبارك فيك! حياك الله ومشكور على الدعم 🙏", + "direction": "rtl" + }, + "provider": "allam", + "model": "allam-v1", + "fallback_used": false, + "tokens_used": 130, + "cost_usd": 0.006, + "credits_used": 6 }, "errors": [], - "request_id": "req_ghi789jkl012" + "request_id": "req_nw_ghi789jkl012" } ``` - + ```bash curl -X POST https://api.trynawa.com/v1/classify \ - -H "Authorization: Bearer nawa_test_sk_xxx" \ + -H "Authorization: Bearer nawa_live_sk_xxx" \ -H "Content-Type: application/json" \ - -d '{"text": "الصوت وحش أوي في الفيديو ده", "platform": "youtube"}' + -d '{"text": "الصوت وحش أوي في الفيديو ده"}' ``` Response: @@ -285,32 +303,38 @@ result = nawa.classify( { "success": true, "result": { - "text": "الصوت وحش أوي في الفيديو ده", - "intent": "complaint", - "intent_confidence": 0.94, + "id": "cls_nw_egy_complaint_001", + "object": "classification", + "intent": ["complaint"], "sentiment": "negative", - "sentiment_confidence": 0.96, + "language": "ar", "dialect": "egyptian", "dialect_confidence": 0.97, - "toxicity": "none", - "toxicity_confidence": 0.95, - "categories": ["feedback"], - "language": "ar", - "model": "nagl-v1", - "cached": false + "requires_response": true, + "priority": "high", + "suggested_reply": { + "text": "معلش، هنشتغل على جودة الصوت في الفيديوهات الجاية. شكرا على الملاحظة!", + "direction": "rtl" + }, + "provider": "allam", + "model": "allam-v1", + "fallback_used": false, + "tokens_used": 125, + "cost_usd": 0.006, + "credits_used": 6 }, "errors": [], - "request_id": "req_mno345pqr678" + "request_id": "req_nw_mno345pqr678" } ``` - + ```bash curl -X POST https://api.trynawa.com/v1/classify \ - -H "Authorization: Bearer nawa_test_sk_xxx" \ + -H "Authorization: Bearer nawa_live_sk_xxx" \ -H "Content-Type: application/json" \ - -d '{"text": "لو سمحت حاول تحكي عن المطاعم بلبنان", "platform": "instagram"}' + -d '{"text": "Great video! But when is the next part coming out?"}' ``` Response: @@ -318,23 +342,38 @@ result = nawa.classify( { "success": true, "result": { - "text": "لو سمحت حاول تحكي عن المطاعم بلبنان", - "intent": "suggestion", - "intent_confidence": 0.92, - "sentiment": "neutral", - "sentiment_confidence": 0.88, - "dialect": "levantine", - "dialect_confidence": 0.96, - "toxicity": "none", - "toxicity_confidence": 0.99, - "categories": ["engagement"], - "language": "ar", - "model": "nagl-v1", - "cached": false + "id": "cls_nw_multi_001", + "object": "classification", + "intent": ["praise", "question"], + "sentiment": "positive", + "language": "en", + "dialect": null, + "dialect_confidence": null, + "requires_response": true, + "priority": "medium", + "suggested_reply": { + "text": "Thank you! The next part is in the works -- stay tuned!", + "direction": "ltr" + }, + "provider": "claude", + "model": "claude-v1", + "fallback_used": false, + "tokens_used": 105, + "cost_usd": 0.006, + "credits_used": 6 }, "errors": [], - "request_id": "req_stu901vwx234" + "request_id": "req_nw_multi_001" } ``` + + + ```bash + curl -X POST "https://api.trynawa.com/v1/classify?provider=allam" \ + -H "Authorization: Bearer nawa_live_sk_xxx" \ + -H "Content-Type: application/json" \ + -d '{"text": "لو سمحت حاول تحكي عن المطاعم بلبنان"}' + ``` + diff --git a/api-reference/comments-reply.mdx b/api-reference/comments-reply.mdx index d6321d7..9cffc91 100644 --- a/api-reference/comments-reply.mdx +++ b/api-reference/comments-reply.mdx @@ -1,60 +1,95 @@ --- title: "Reply to Comment" -sidebarTitle: "POST /v1/comments/:id/reply" -description: "Generate a context-aware reply to a comment in Arabic or English." -api: "POST https://api.trynawa.com/v1/comments/{id}/reply" +sidebarTitle: "POST /v1/comments/reply" +description: "Classify a comment and generate a context-aware reply in a single API call." +api: "POST https://api.trynawa.com/v1/comments/reply" --- -Generate an AI-powered reply that matches the commenter's language and cultural context. For Arabic comments, replies match the detected dialect (Gulf, Egyptian, Levantine, MSA). For English comments, replies are natural and platform-appropriate. Language is auto-detected unless overridden. +Classify a comment and generate an AI-powered reply in one request. For Arabic comments, replies match the detected dialect (Gulf, Egyptian, Levantine, MSA). For English comments, replies are natural and platform-appropriate. - Cost: **$0.008** per request (8 credits). Semantic cache hits are free (`X-NAWA-Cache: HIT`). + Cost: **$0.008** per request (8 credits). This endpoint performs classification and reply generation in a single call. ## Request -### Path parameters +### Headers + +| Header | Required | Description | +|--------|----------|-------------| +| `Authorization` | Yes | `Bearer nawa_live_sk_xxx` or `Bearer nawa_test_sk_xxx` | +| `Content-Type` | Yes | `application/json` | + +### Query parameters | Parameter | Type | Required | Description | |-----------|------|----------|-------------| -| `id` | string | Yes | The comment ID to reply to. | +| `provider` | string | No | Force a specific AI provider: `claude`, `gemini`, or `allam`. | ### Body parameters | Parameter | Type | Required | Description | |-----------|------|----------|-------------| -| `tone` | string | No | Reply tone: `friendly`, `professional`, `casual`, `formal`. Default: `friendly`. | -| `max_length` | integer | No | Maximum reply length in characters. Default: 500. | -| `context` | string | No | Additional context about the channel or video to improve reply relevance. | -| `language` | string | No | Force reply language: `ar`, `en`, `auto`. Default: `auto` (matches commenter's language). | +| `text` | string | Yes | The comment text to reply to. Min 1 character. | +| `tone` | string | No | Reply tone: `friendly`, `professional`, `casual`, `formal`. Default: `professional`. | +| `max_length` | integer | No | Maximum reply length in characters (1--2000). Default: 500. | +| `context.platform` | string | No | Source platform for context: `youtube`, `instagram`, `twitter`, `facebook`. | +| `context.brand_voice` | string | No | Brand voice description to influence the reply tone. | ### Example request ```bash cURL -curl -X POST https://api.trynawa.com/v1/comments/cmt_abc123/reply \ - -H "Authorization: Bearer nawa_test_sk_xxx" \ +curl -X POST https://api.trynawa.com/v1/comments/reply \ + -H "Authorization: Bearer nawa_live_sk_xxx" \ -H "Content-Type: application/json" \ -d '{ + "text": "متى الجزء الثاني؟", "tone": "friendly", - "context": "Tech review channel focused on smartphones" + "context": { + "platform": "youtube", + "brand_voice": "Tech review channel focused on smartphones" + } }' ``` ```typescript TypeScript -const { data, error } = await nawa.comments.reply('cmt_abc123', { +import { Nawa } from '@nawalabs/sdk' + +const nawa = new Nawa({ apiKey: process.env.NAWA_API_KEY }) + +const { data, error } = await nawa.comments.reply({ + text: 'متى الجزء الثاني؟', tone: 'friendly', - context: 'Tech review channel focused on smartphones' + context: { + platform: 'youtube', + brandVoice: 'Tech review channel focused on smartphones' + } }) + +if (data) { + console.log(data.reply.text) + console.log(data.classification.intent) +} ``` ```python Python +from nawa import Nawa + +nawa = Nawa(api_key="your_api_key") + result = nawa.comments.reply( - comment_id="cmt_abc123", + text="متى الجزء الثاني؟", tone="friendly", - context="Tech review channel focused on smartphones" + context={ + "platform": "youtube", + "brand_voice": "Tech review channel focused on smartphones" + } ) + +print(result.reply.text) +print(result.classification.intent) ``` @@ -67,15 +102,26 @@ result = nawa.comments.reply( { "success": true, "result": { - "comment_id": "cmt_abc123", - "reply_text": "إن شاء الله الجزء الثاني قريب! تابعنا عشان ما يفوتك 🔔", - "reply_dialect": "gulf", - "tone": "friendly", - "original_intent": "question", - "original_dialect": "gulf" + "id": "rpl_nw_pon1yom9bkfe", + "object": "comment_reply", + "classification": { + "intent": ["question"], + "sentiment": "neutral", + "priority": "medium", + "requires_response": true + }, + "reply": { + "text": "إن شاء الله الجزء الثاني قريب! تابعنا عشان ما يفوتك 🔔", + "direction": "rtl", + "tone": "friendly" + }, + "provider": "allam", + "model": "allam-v1", + "cost_usd": 0.008, + "credits_used": 8 }, "errors": [], - "request_id": "req_rep789xyz012" + "request_id": "req_nw_rep789xyz012" } ``` @@ -83,9 +129,87 @@ result = nawa.comments.reply( | Field | Type | Description | |-------|------|-------------| -| `comment_id` | string | The comment that was replied to | -| `reply_text` | string | The generated reply text | -| `reply_dialect` | string \| null | Dialect used in the reply (matches original). `null` for English replies. | -| `tone` | string | The tone used for the reply | -| `original_intent` | string | Detected intent of the original comment | -| `original_dialect` | string | Detected dialect of the original comment | +| `id` | string | Unique reply ID (format: `rpl_nw_xxx`) | +| `object` | string | Always `"comment_reply"` | +| `classification.intent` | string[] | Detected intent(s) of the original comment | +| `classification.sentiment` | string | Detected sentiment of the original comment | +| `classification.priority` | string | Response priority: `high`, `medium`, or `low` | +| `classification.requires_response` | boolean | Whether this comment warrants a reply | +| `reply.text` | string | The generated reply text | +| `reply.direction` | string | Text direction: `ltr` or `rtl` | +| `reply.tone` | string | The tone applied to the reply | +| `provider` | string | AI provider used: `claude`, `gemini`, or `allam` | +| `model` | string | Specific model version used | +| `cost_usd` | number | Cost of this request in USD | +| `credits_used` | integer | Credits deducted from your balance | + +### Error responses + +| Status | Type | When | +|--------|------|------| +| 400 | `invalid_request_error` | Missing `text`, invalid `tone`, `max_length` out of range | +| 401 | `authentication_error` | Invalid or missing API key | +| 402 | `insufficient_credits` | No credits remaining | +| 429 | `rate_limit_error` | Rate limit exceeded | +| 500 | `api_error` | Internal or provider error | + +### More examples + + + + ```bash + curl -X POST https://api.trynawa.com/v1/comments/reply \ + -H "Authorization: Bearer nawa_live_sk_xxx" \ + -H "Content-Type: application/json" \ + -d '{ + "text": "The audio quality is terrible in this one.", + "tone": "professional", + "context": { "platform": "youtube" } + }' + ``` + + Response: + ```json + { + "success": true, + "result": { + "id": "rpl_nw_en_prof_001", + "object": "comment_reply", + "classification": { + "intent": ["complaint"], + "sentiment": "negative", + "priority": "high", + "requires_response": true + }, + "reply": { + "text": "Thank you for the feedback. We've noted the audio issue and will improve it in upcoming videos.", + "direction": "ltr", + "tone": "professional" + }, + "provider": "claude", + "model": "claude-v1", + "cost_usd": 0.008, + "credits_used": 8 + }, + "errors": [], + "request_id": "req_nw_en_prof_001" + } + ``` + + + + ```bash + curl -X POST https://api.trynawa.com/v1/comments/reply \ + -H "Authorization: Bearer nawa_live_sk_xxx" \ + -H "Content-Type: application/json" \ + -d '{ + "text": "ما شاء الله عليك، محتوى رهيب!", + "tone": "friendly", + "context": { + "platform": "youtube", + "brand_voice": "Fun and energetic cooking channel" + } + }' + ``` + + diff --git a/api-reference/detect.mdx b/api-reference/detect.mdx index 2169b2c..2baf45f 100644 --- a/api-reference/detect.mdx +++ b/api-reference/detect.mdx @@ -83,6 +83,8 @@ result = nawa.detect(text="وش رايكم بالمحتوى الجديد؟") | Field | Type | Description | |-------|------|-------------| +| `id` | string | Unique detection ID (format: `det_nw_xxx`) | +| `object` | string | Always `"detection"` | | `text` | string | The original input text | | `language` | string | Detected language: `ar`, `en`, or `mixed` | | `dialect` | string or null | Detected Arabic dialect: `gulf`, `egyptian`, `levantine`, `msa`. Null if not Arabic. | diff --git a/api-reference/feedback.mdx b/api-reference/feedback.mdx index 4cddf8b..e245645 100644 --- a/api-reference/feedback.mdx +++ b/api-reference/feedback.mdx @@ -17,14 +17,22 @@ Submit reinforcement learning from human feedback (RLHF) to continuously improve ## Request +### Headers + +| Header | Required | Description | +|--------|----------|-------------| +| `Authorization` | Yes | `Bearer nawa_live_sk_xxx` or `Bearer nawa_test_sk_xxx` | +| `Content-Type` | Yes | `application/json` | + ### Body parameters | Parameter | Type | Required | Description | |-----------|------|----------|-------------| -| `request_id` | string | Yes | The `request_id` from the original classification response. | -| `field` | string | Yes | The field to correct: `intent`, `sentiment`, `dialect`, `toxicity`, `category`. | -| `expected_value` | string | Yes | The correct value the model should have returned. | -| `comment` | string | No | Optional free-text explanation of why this correction is needed. | +| `classification_id` | string | Yes | The classification ID (format: `cls_nw_xxx`) from the original classify response. | +| `rating` | string | Yes | Your assessment: `correct`, `incorrect`, or `partial`. | +| `corrected_intent` | string[] | No | The correct intent(s) the model should have returned. | +| `corrected_sentiment` | string | No | The correct sentiment: `positive`, `negative`, `neutral`, or `mixed`. | +| `comment` | string | No | Free-text explanation of why this correction is needed. | ### Example request @@ -32,30 +40,41 @@ Submit reinforcement learning from human feedback (RLHF) to continuously improve ```bash cURL curl -X POST https://api.trynawa.com/v1/feedback \ - -H "Authorization: Bearer nawa_test_sk_xxx" \ + -H "Authorization: Bearer nawa_live_sk_xxx" \ -H "Content-Type: application/json" \ -d '{ - "request_id": "req_abc123def456", - "field": "dialect", - "expected_value": "levantine", + "classification_id": "cls_nw_abc123def456", + "rating": "incorrect", + "corrected_intent": ["question"], + "corrected_sentiment": "neutral", "comment": "This is Lebanese Arabic, not Gulf" }' ``` ```typescript TypeScript +import { Nawa } from '@nawalabs/sdk' + +const nawa = new Nawa({ apiKey: process.env.NAWA_API_KEY }) + const { data, error } = await nawa.feedback.submit({ - requestId: 'req_abc123def456', - field: 'dialect', - expectedValue: 'levantine', + classificationId: 'cls_nw_abc123def456', + rating: 'incorrect', + correctedIntent: ['question'], + correctedSentiment: 'neutral', comment: 'This is Lebanese Arabic, not Gulf' }) ``` ```python Python +from nawa import Nawa + +nawa = Nawa(api_key="your_api_key") + result = nawa.feedback.submit( - request_id="req_abc123def456", - field="dialect", - expected_value="levantine", + classification_id="cls_nw_abc123def456", + rating="incorrect", + corrected_intent=["question"], + corrected_sentiment="neutral", comment="This is Lebanese Arabic, not Gulf" ) ``` @@ -70,11 +89,32 @@ result = nawa.feedback.submit( { "success": true, "result": { - "feedback_id": "fb_xyz789", - "status": "accepted", - "message": "Thank you! Your feedback helps improve NAWA's accuracy." + "id": "fb_nw_xyz789", + "object": "feedback", + "classification_id": "cls_nw_abc123def456", + "rating": "incorrect", + "acknowledged": true }, "errors": [], - "request_id": "req_fb_abc123" + "request_id": "req_nw_fb_abc123" } ``` + +### Result fields + +| Field | Type | Description | +|-------|------|-------------| +| `id` | string | Unique feedback ID (format: `fb_nw_xxx`) | +| `object` | string | Always `"feedback"` | +| `classification_id` | string | The classification this feedback applies to | +| `rating` | string | The rating you submitted | +| `acknowledged` | boolean | Always `true` on success | + +### Error responses + +| Status | Type | When | +|--------|------|------| +| 400 | `invalid_request_error` | Missing `classification_id` or `rating`, invalid rating value | +| 401 | `authentication_error` | Invalid or missing API key | +| 404 | `not_found_error` | Classification ID does not exist | +| 500 | `api_error` | Internal error | diff --git a/api-reference/health.mdx b/api-reference/health.mdx index ca110e8..1d6b46f 100644 --- a/api-reference/health.mdx +++ b/api-reference/health.mdx @@ -5,14 +5,41 @@ description: "Check the operational status of the NAWA API and its dependencies. api: "GET https://api.trynawa.com/v1/health" --- -Check the operational status of the NAWA API. This endpoint is **free** and does **not** require authentication. +Check the operational status of the NAWA API and its backing services. This endpoint is **free** and does **not** require authentication. ## Request -```bash + + +```bash cURL curl https://api.trynawa.com/v1/health ``` +```typescript TypeScript +const response = await fetch('https://api.trynawa.com/v1/health') +const data = await response.json() + +if (data.result.status === 'healthy') { + console.log('All systems operational') +} else { + console.log('Degraded:', data.result.services) +} +``` + +```python Python +import requests + +response = requests.get("https://api.trynawa.com/v1/health") +data = response.json() + +if data["result"]["status"] == "healthy": + print("All systems operational") +else: + print("Degraded:", data["result"]["services"]) +``` + + + ## Response ### Healthy response (200) @@ -22,41 +49,71 @@ curl https://api.trynawa.com/v1/health "success": true, "result": { "status": "healthy", - "version": "1.0.0", + "version": "v1", "services": { - "api": "operational", - "classification": "operational", - "database": "operational", - "cache": "operational" + "database": { + "status": "operational", + "latency_ms": 12 + }, + "redis": { + "status": "operational", + "latency_ms": 3 + }, + "nagl": { + "status": "operational" + } }, - "timestamp": "2025-01-15T12:00:00Z" + "timestamp": "2025-01-15T12:00:00Z", + "latency_ms": 15 }, "errors": [], - "request_id": "req_hlt_abc123" + "request_id": "req_nw_hlt_abc123" } ``` -### Degraded response (200) +### Degraded response (503) + +When one or more services are unhealthy, the endpoint returns a 503 status: ```json { "success": true, "result": { "status": "degraded", - "version": "1.0.0", + "version": "v1", "services": { - "api": "operational", - "classification": "degraded", - "database": "operational", - "cache": "operational" + "database": { + "status": "operational", + "latency_ms": 12 + }, + "redis": { + "status": "degraded", + "latency_ms": 450 + }, + "nagl": { + "status": "operational" + } }, - "timestamp": "2025-01-15T12:00:00Z" + "timestamp": "2025-01-15T12:00:00Z", + "latency_ms": 462 }, "errors": [], - "request_id": "req_hlt_def456" + "request_id": "req_nw_hlt_def456" } ``` +### Result fields + +| Field | Type | Description | +|-------|------|-------------| +| `status` | string | Overall status: `healthy` or `degraded` | +| `version` | string | API version (`v1`) | +| `services.database` | object | Database status and latency | +| `services.redis` | object | Redis cache status and latency | +| `services.nagl` | object | NAGL engine status | +| `timestamp` | string | ISO 8601 timestamp of the check | +| `latency_ms` | integer | Total health check latency in milliseconds | + For real-time status monitoring, visit [status.trynawa.com](https://status.trynawa.com). diff --git a/api-reference/moderate.mdx b/api-reference/moderate.mdx index 947d30e..abbde7c 100644 --- a/api-reference/moderate.mdx +++ b/api-reference/moderate.mdx @@ -184,6 +184,8 @@ When content is flagged, the response includes specific flags, severity scores, | Field | Type | Description | |-------|------|-------------| +| `id` | string | Unique moderation ID (format: `mod_nw_xxx`) | +| `object` | string | Always `"moderation"` | | `text` | string | The original input text | | `is_safe` | boolean | Whether the content passed moderation | | `verdict` | string | `safe` or `flagged` | diff --git a/api-reference/rubric-classify.mdx b/api-reference/rubric-classify.mdx index 4489175..d17c026 100644 --- a/api-reference/rubric-classify.mdx +++ b/api-reference/rubric-classify.mdx @@ -1,11 +1,11 @@ --- title: "Rubric Classify" sidebarTitle: "POST /v1/rubric/classify" -description: "Classify a comment against a custom rubric with predefined scoring criteria." +description: "Classify text against a custom rubric with user-defined categories and confidence thresholds." api: "POST https://api.trynawa.com/v1/rubric/classify" --- -Classify a comment against a custom rubric. Define your own categories and scoring criteria for domain-specific classification. +Classify text against a custom rubric. Define your own categories with descriptions, enable multi-label classification, and set confidence thresholds for domain-specific workflows. Cost: **$0.003** per request (3 credits). **500 free requests/month** on this endpoint -- no credit card required. Semantic cache hits are free (`X-NAWA-Cache: HIT`). @@ -13,15 +13,28 @@ Classify a comment against a custom rubric. Define your own categories and scori ## Request +### Headers + +| Header | Required | Description | +|--------|----------|-------------| +| `Authorization` | Yes | `Bearer nawa_live_sk_xxx` or `Bearer nawa_test_sk_xxx` | +| `Content-Type` | Yes | `application/json` | + +### Query parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `provider` | string | No | Force a specific AI provider: `claude`, `gemini`, or `allam`. | + ### Body parameters | Parameter | Type | Required | Description | |-----------|------|----------|-------------| -| `text` | string | Yes | The comment text to classify. Max 5,000 characters. | -| `rubric` | object | Yes | The rubric definition with categories and criteria. | -| `rubric.categories` | string[] | Yes | List of category names to classify against. | -| `rubric.descriptions` | object | No | Category descriptions to guide the model. Keys are category names, values are description strings. | -| `platform` | string | No | Source platform for context. | +| `text` | string | Yes | The text to classify. Min 1 character. | +| `rubric` | object | Yes | The rubric definition. | +| `rubric.categories` | array | Yes | Array of category objects. Each object has a `name` (string, required) and optional `description` (string). 1--20 categories allowed. | +| `rubric.multi_label` | boolean | No | Allow multiple category matches. Default: `false`. | +| `rubric.confidence_threshold` | number | No | Minimum confidence score to include a category (0.0--1.0). Default: `0.5`. | ### Example request @@ -29,52 +42,60 @@ Classify a comment against a custom rubric. Define your own categories and scori ```bash cURL curl -X POST https://api.trynawa.com/v1/rubric/classify \ - -H "Authorization: Bearer nawa_test_sk_xxx" \ + -H "Authorization: Bearer nawa_live_sk_xxx" \ -H "Content-Type: application/json" \ -d '{ "text": "وين الترجمة العربية؟ مافهمت شي", "rubric": { - "categories": ["translation_request", "technical_issue", "content_feedback", "off_topic"], - "descriptions": { - "translation_request": "User is asking for subtitles or translation", - "technical_issue": "Audio, video, or playback problems", - "content_feedback": "Comments about the content quality", - "off_topic": "Not related to the video" - } - }, - "platform": "youtube" + "categories": [ + { "name": "translation_request", "description": "User is asking for subtitles or translation" }, + { "name": "technical_issue", "description": "Audio, video, or playback problems" }, + { "name": "content_feedback", "description": "Comments about the content quality" }, + { "name": "off_topic", "description": "Not related to the video" } + ], + "multi_label": false, + "confidence_threshold": 0.5 + } }' ``` ```typescript TypeScript +import { Nawa } from '@nawalabs/sdk' + +const nawa = new Nawa({ apiKey: process.env.NAWA_API_KEY }) + const { data, error } = await nawa.rubric.classify({ text: 'وين الترجمة العربية؟ مافهمت شي', rubric: { - categories: ['translation_request', 'technical_issue', 'content_feedback', 'off_topic'], - descriptions: { - translation_request: 'User is asking for subtitles or translation', - technical_issue: 'Audio, video, or playback problems', - content_feedback: 'Comments about the content quality', - off_topic: 'Not related to the video' - } - }, - platform: 'youtube' + categories: [ + { name: 'translation_request', description: 'User is asking for subtitles or translation' }, + { name: 'technical_issue', description: 'Audio, video, or playback problems' }, + { name: 'content_feedback', description: 'Comments about the content quality' }, + { name: 'off_topic', description: 'Not related to the video' } + ], + multiLabel: false, + confidenceThreshold: 0.5 + } }) ``` ```python Python +from nawa import Nawa + +nawa = Nawa(api_key="your_api_key") + result = nawa.rubric.classify( text="وين الترجمة العربية؟ مافهمت شي", rubric={ - "categories": ["translation_request", "technical_issue", "content_feedback", "off_topic"], - "descriptions": { - "translation_request": "User is asking for subtitles or translation", - "technical_issue": "Audio, video, or playback problems", - "content_feedback": "Comments about the content quality", - "off_topic": "Not related to the video", - }, + "categories": [ + {"name": "translation_request", "description": "User is asking for subtitles or translation"}, + {"name": "technical_issue", "description": "Audio, video, or playback problems"}, + {"name": "content_feedback", "description": "Comments about the content quality"}, + {"name": "off_topic", "description": "Not related to the video"}, + ], + "multi_label": False, + "confidence_threshold": 0.5, }, - platform="youtube", ) ``` @@ -88,23 +109,24 @@ result = nawa.rubric.classify( { "success": true, "result": { - "text": "وين الترجمة العربية؟ مافهمت شي", - "category": "translation_request", - "category_confidence": 0.94, - "scores": { - "translation_request": 0.94, - "technical_issue": 0.03, - "content_feedback": 0.02, - "off_topic": 0.01 - }, - "dialect": "gulf", - "dialect_confidence": 0.91, + "id": "rcl_nw_pon1yom9bkfe", + "object": "rubric_classification", + "categories": [ + { "name": "translation_request", "confidence": 0.94 }, + { "name": "technical_issue", "confidence": 0.03 }, + { "name": "content_feedback", "confidence": 0.02 }, + { "name": "off_topic", "confidence": 0.01 } + ], + "multi_label": false, "language": "ar", - "model": "nagl-v1", - "cached": false + "provider": "allam", + "model": "allam-v1", + "fallback_used": false, + "cost_usd": 0.003, + "credits_used": 3 }, "errors": [], - "request_id": "req_rub123abc456" + "request_id": "req_nw_rub123abc456" } ``` @@ -112,10 +134,27 @@ result = nawa.rubric.classify( | Field | Type | Description | |-------|------|-------------| -| `category` | string | The top matching category from your rubric | -| `category_confidence` | number | Confidence score (0–1) for the top category | -| `scores` | object | Confidence scores for all rubric categories | -| `dialect` | string | Detected Arabic dialect | -| `dialect_confidence` | number | Dialect confidence score (0–1) | -| `language` | string | Detected language code | -| `cached` | boolean | Whether served from semantic cache | +| `id` | string | Unique rubric classification ID (format: `rcl_nw_xxx`) | +| `object` | string | Always `"rubric_classification"` | +| `categories` | array | Array of category results, each with `name` (string) and `confidence` (number, 0--1). Sorted by confidence descending. | +| `multi_label` | boolean | Whether multi-label classification was used | +| `language` | string | Detected language: `ar`, `en`, or `mixed` | +| `provider` | string | AI provider used: `claude`, `gemini`, or `allam` | +| `model` | string | Specific model version used | +| `fallback_used` | boolean | Whether a fallback provider was used | +| `cost_usd` | number | Cost of this request in USD | +| `credits_used` | integer | Credits deducted from your balance | + +### Error responses + +| Status | Type | When | +|--------|------|------| +| 400 | `invalid_request_error` | Missing `text`, missing or invalid `rubric`, too many categories (max 20) | +| 401 | `authentication_error` | Invalid or missing API key | +| 402 | `insufficient_credits` | No credits remaining | +| 429 | `rate_limit_error` | Rate limit exceeded | +| 500 | `api_error` | Internal or provider error | + + + Use `multi_label: true` when comments may match more than one category. For example, "The audio is bad and where are the subtitles?" could match both `technical_issue` and `translation_request`. + diff --git a/api-reference/translate.mdx b/api-reference/translate.mdx index c10d2ba..8a1e883 100644 --- a/api-reference/translate.mdx +++ b/api-reference/translate.mdx @@ -107,6 +107,8 @@ Translate text between English and Arabic with dialect awareness. Generates cult | Field | Type | Description | |-------|------|-------------| +| `id` | string | Unique translation ID (format: `trn_nw_xxx`) | +| `object` | string | Always `"translation"` | | `text` | string | The original input text | | `translated_text` | string | The translated output | | `source_language` | string | Detected or specified source language | diff --git a/api-reference/usage.mdx b/api-reference/usage.mdx index d4b1b6b..c7e462c 100644 --- a/api-reference/usage.mdx +++ b/api-reference/usage.mdx @@ -9,21 +9,61 @@ Retrieve your API usage statistics including request counts, credit consumption, ## Request +### Headers + +| Header | Required | Description | +|--------|----------|-------------| +| `Authorization` | Yes | `Bearer nawa_live_sk_xxx` or `Bearer nawa_test_sk_xxx` | + ### Query parameters | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `from` | string | No | Start date (ISO 8601). Default: start of current month. | | `to` | string | No | End date (ISO 8601). Default: now. | -| `group_by` | string | No | Group by: `day`, `week`, `month`, `endpoint`. Default: `day`. | +| `group_by` | string | No | Group results by: `endpoint` or `day`. Default: `endpoint`. | ### Example request -```bash + + +```bash cURL curl "https://api.trynawa.com/v1/usage?from=2025-01-01T00:00:00Z&group_by=endpoint" \ - -H "Authorization: Bearer nawa_test_sk_xxx" + -H "Authorization: Bearer nawa_live_sk_xxx" +``` + +```typescript TypeScript +import { Nawa } from '@nawalabs/sdk' + +const nawa = new Nawa({ apiKey: process.env.NAWA_API_KEY }) + +const { data, error } = await nawa.usage({ + from: '2025-01-01T00:00:00Z', + groupBy: 'endpoint' +}) + +if (data) { + console.log(`Total requests: ${data.usage.total_requests}`) + console.log(`Cache hit rate: ${data.usage.cache_hit_rate}`) +} ``` +```python Python +from nawa import Nawa + +nawa = Nawa(api_key="your_api_key") + +result = nawa.usage( + from_date="2025-01-01T00:00:00Z", + group_by="endpoint" +) + +print(f"Total requests: {result.usage.total_requests}") +print(f"Cache hit rate: {result.usage.cache_hit_rate}") +``` + + + ## Response ### Success response (200) @@ -32,44 +72,39 @@ curl "https://api.trynawa.com/v1/usage?from=2025-01-01T00:00:00Z&group_by=endpoi { "success": true, "result": { - "period": { - "from": "2025-01-01T00:00:00Z", - "to": "2025-01-31T23:59:59Z" + "usage": { + "total_requests": 12450, + "total_cost": 68.70, + "cache_hits": 2835, + "cache_hit_rate": 0.23, + "period": { + "from": "2025-01-01T00:00:00Z", + "to": "2025-01-31T23:59:59Z" + } }, - "total_requests": 12450, - "total_cost": 68.70, - "cache_hit_rate": 0.23, "by_endpoint": [ { "endpoint": "/v1/classify", "requests": 8500, "cost": 51.00, - "cache_hits": 1955, - "avg_latency_ms": 820 + "cache_hits": 1955 }, { "endpoint": "/v1/rubric/classify", "requests": 2200, "cost": 6.60, - "cache_hits": 880, - "avg_latency_ms": 650 + "cache_hits": 880 }, { - "endpoint": "/v1/comments/:id/reply", + "endpoint": "/v1/comments/reply", "requests": 1750, "cost": 14.00, - "cache_hits": 0, - "avg_latency_ms": 1200 + "cache_hits": 0 } - ], - "balance": { - "current": 31.30, - "credits_purchased": 100.00, - "credits_used": 68.70 - } + ] }, "errors": [], - "request_id": "req_usg_abc123" + "request_id": "req_nw_usg_abc123" } ``` @@ -77,8 +112,18 @@ curl "https://api.trynawa.com/v1/usage?from=2025-01-01T00:00:00Z&group_by=endpoi | Field | Type | Description | |-------|------|-------------| -| `total_requests` | integer | Total API requests in the period | -| `total_cost` | number | Total credit cost in USD | -| `cache_hit_rate` | number | Percentage of requests served from cache (0–1) | -| `by_endpoint` | array | Breakdown by endpoint | -| `balance` | object | Current balance and credit history | +| `usage.total_requests` | integer | Total API requests in the period | +| `usage.total_cost` | number | Total credit cost in USD | +| `usage.cache_hits` | integer | Number of requests served from cache | +| `usage.cache_hit_rate` | number | Fraction of requests served from cache (0--1) | +| `usage.period.from` | string or null | Start of the usage period | +| `usage.period.to` | string or null | End of the usage period | +| `by_endpoint` | array | Breakdown by endpoint (when `group_by=endpoint`) | +| `by_day` | array | Breakdown by date (when `group_by=day`) | + +### Error responses + +| Status | Type | When | +|--------|------|------| +| 401 | `authentication_error` | Invalid or missing API key | +| 500 | `api_error` | Internal error | diff --git a/api-reference/webhooks-manage.mdx b/api-reference/webhooks-manage.mdx new file mode 100644 index 0000000..7831b09 --- /dev/null +++ b/api-reference/webhooks-manage.mdx @@ -0,0 +1,192 @@ +--- +title: "Manage Webhooks" +sidebarTitle: "Webhooks" +description: "Create, list, and delete webhook endpoints for real-time event notifications." +--- + +Manage your webhook endpoints to receive real-time notifications when events occur in your NAWA account. See the [webhooks overview](/webhooks) for event types, payload format, and signature verification. + +## Create a webhook + +**POST** `https://api.trynawa.com/v1/webhooks` + +Register a new webhook endpoint to receive event notifications. + +### Body parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `url` | string | Yes | The HTTPS URL to receive webhook events. Must use HTTPS. | +| `events` | string[] | Yes | Event types to subscribe to. | + +**Supported events:** `classification.completed`, `classification.failed`, `credits.low`, `credits.exhausted` + +### Example request + + + +```bash cURL +curl -X POST https://api.trynawa.com/v1/webhooks \ + -H "Authorization: Bearer nawa_live_sk_xxx" \ + -H "Content-Type: application/json" \ + -d '{ + "url": "https://example.com/webhooks/nawa", + "events": ["classification.completed", "credits.low"] + }' +``` + +```typescript TypeScript +import { Nawa } from '@nawalabs/sdk' + +const nawa = new Nawa({ apiKey: process.env.NAWA_API_KEY }) + +const { data, error } = await nawa.webhooks.create({ + url: 'https://example.com/webhooks/nawa', + events: ['classification.completed', 'credits.low'] +}) + +// Store the signing secret securely -- it is shown only once +console.log(data.signing_secret) +``` + +```python Python +from nawa import Nawa + +nawa = Nawa(api_key="your_api_key") + +result = nawa.webhooks.create( + url="https://example.com/webhooks/nawa", + events=["classification.completed", "credits.low"] +) + +# Store the signing secret securely -- it is shown only once +print(result.signing_secret) +``` + + + +### Success response (201) + +```json +{ + "success": true, + "result": { + "id": "wh_abc123", + "url": "https://example.com/webhooks/nawa", + "events": ["classification.completed", "credits.low"], + "signing_secret": "nawa_wh_sk_abc123def456", + "active": true, + "created_at": "2025-01-15T12:00:00Z" + }, + "errors": [], + "request_id": "req_nw_wh_abc123" +} +``` + + + The `signing_secret` is shown only once at creation time. Store it securely. You will need it to [verify webhook signatures](/webhooks#signature-verification). + + +--- + +## List webhooks + +**GET** `https://api.trynawa.com/v1/webhooks` + +Retrieve all registered webhook endpoints for your account. + +### Example request + + + +```bash cURL +curl https://api.trynawa.com/v1/webhooks \ + -H "Authorization: Bearer nawa_live_sk_xxx" +``` + +```typescript TypeScript +const { data, error } = await nawa.webhooks.list() +``` + +```python Python +result = nawa.webhooks.list() +``` + + + +### Success response (200) + +```json +{ + "success": true, + "result": { + "webhooks": [ + { + "id": "wh_abc123", + "url": "https://example.com/webhooks/nawa", + "events": ["classification.completed", "credits.low"], + "active": true, + "created_at": "2025-01-15T12:00:00Z" + } + ] + }, + "errors": [], + "request_id": "req_nw_wh_list_001" +} +``` + +--- + +## Delete a webhook + +**DELETE** `https://api.trynawa.com/v1/webhooks?id={webhook_id}` + +Deactivate and remove a webhook endpoint. + +### Query parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `id` | string | Yes | The webhook ID to delete. | + +### Example request + + + +```bash cURL +curl -X DELETE "https://api.trynawa.com/v1/webhooks?id=wh_abc123" \ + -H "Authorization: Bearer nawa_live_sk_xxx" +``` + +```typescript TypeScript +const { data, error } = await nawa.webhooks.delete('wh_abc123') +``` + +```python Python +result = nawa.webhooks.delete("wh_abc123") +``` + + + +### Success response (200) + +```json +{ + "success": true, + "result": { + "id": "wh_abc123", + "deleted": true + }, + "errors": [], + "request_id": "req_nw_wh_del_001" +} +``` + +### Error responses (all operations) + +| Status | Type | When | +|--------|------|------| +| 400 | `invalid_request_error` | Missing `url` or `events`, invalid URL (not HTTPS), invalid event type | +| 401 | `authentication_error` | Invalid or missing API key | +| 404 | `not_found_error` | Webhook ID does not exist | +| 500 | `api_error` | Internal error | diff --git a/docs.json b/docs.json index 8f8f901..9ec6df8 100644 --- a/docs.json +++ b/docs.json @@ -62,7 +62,8 @@ "api-reference/comments-list", "api-reference/analytics", "api-reference/health", - "api-reference/usage" + "api-reference/usage", + "api-reference/webhooks-manage" ] } ]