Uploading Cognigy.AI Training Datasets via REST API with Go

Uploading Cognigy.AI Training Datasets via REST API with Go

What You Will Build

A production-grade Go module that uploads conversational AI training datasets to the Cognigy.AI/NICE CXone AI platform using atomic POST requests. The implementation validates JSON schemas against machine learning engine constraints, enforces maximum file size limits, detects duplicate utterances, and triggers automatic model retraining. The module exposes a unified uploader interface that tracks latency, calculates parsing success rates, generates structured audit logs for ML governance, and synchronizes upload events with external version control systems via webhook callbacks.

Prerequisites

  • OAuth 2.0 client credentials with scopes: cognigy:dataset:write, cognigy:dataset:read, cognigy:admin:retrain
  • Cognigy.AI/NICE CXone API v1 base URL (e.g., https://your-instance.cognigy.ai/api/v1)
  • Go 1.21 or higher
  • No external dependencies required; standard library only
  • Access to a webhook receiver endpoint for version control synchronization

Authentication Setup

The Cognigy.AI platform uses OAuth 2.0 for authentication. You must exchange client credentials for a bearer token before issuing dataset operations. The following code establishes a secure HTTP client with token caching and automatic refresh logic.

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"
)

type OAuthTokenResponse struct {
	AccessToken string `json:"access_token"`
	TokenType   string `json:"token_type"`
	ExpiresIn   int    `json:"expires_in"`
}

type OAuthConfig struct {
	BaseURL   string
	ClientID  string
	Secret    string
}

func FetchOAuthToken(cfg OAuthConfig) (string, error) {
	payload := fmt.Sprintf(
		"grant_type=client_credentials&client_id=%s&client_secret=%s&scope=cognigy:dataset:write cognigy:dataset:read cognigy:admin:retrain",
		cfg.ClientID, cfg.Secret,
	)

	req, err := http.NewRequest("POST", fmt.Sprintf("%s/oauth/token", cfg.BaseURL), bytes.NewBufferString(payload))
	if err != nil {
		return "", fmt.Errorf("failed to create oauth request: %w", err)
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	client := &http.Client{Timeout: 10 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return "", fmt.Errorf("oauth request failed: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return "", fmt.Errorf("oauth error %d: %s", resp.StatusCode, string(body))
	}

	var tokenResp OAuthTokenResponse
	if err := json.NewDecoder(resp.Body).Decode(&tokenResp); err != nil {
		return "", fmt.Errorf("failed to decode oauth response: %w", err)
	}

	return tokenResp.AccessToken, nil
}

The FetchOAuthToken function exchanges credentials for an access token. In production, you should cache the token and refresh it when time.Now().Add(time.Duration(expiresIn)*time.Second) approaches expiration. The required scopes are explicitly requested in the scope parameter to satisfy platform authorization policies.

Implementation

Step 1: Payload Construction and Schema Validation

The upload payload must contain dataset identifier references, an utterance count matrix, and label taxonomy directives. The ML engine rejects payloads that violate structural constraints. The following code defines the payload schema and implements validation logic.

type LabelDirective struct {
	Label    string `json:"label"`
	Type     string `json:"type"`
	Priority int    `json:"priority"`
}

type UploadPayload struct {
	DatasetIDRef      string           `json:"datasetIdReference"`
	UtteranceMatrix   json.RawMessage  `json:"utteranceCountMatrix"`
	LabelTaxonomy     []LabelDirective `json:"labelTaxonomyDirectives"`
	Metadata          map[string]string `json:"metadata"`
}

func ValidateUploadSchema(payload UploadPayload) error {
	if payload.DatasetIDRef == "" {
		return fmt.Errorf("datasetIdReference is required")
	}

	if len(payload.LabelTaxonomy) == 0 {
		return fmt.Errorf("labelTaxonomyDirectives must contain at least one directive")
	}

	for _, directive := range payload.LabelTaxonomy {
		if directive.Label == "" || directive.Type == "" || directive.Priority < 0 {
			return fmt.Errorf("invalid label directive: missing label, type, or negative priority")
		}
	}

	var matrix map[string]int
	if err := json.Unmarshal(payload.UtteranceMatrix, &matrix); err != nil {
		return fmt.Errorf("utteranceCountMatrix must be a valid JSON object mapping labels to counts")
	}

	for label, count := range matrix {
		if count < 0 {
			return fmt.Errorf("utterance count for label %s cannot be negative", label)
		}
		if count > 100000 {
			return fmt.Errorf("utterance count for label %s exceeds ML engine limit of 100000", label)
		}
	}

	return nil
}

The ValidateUploadSchema function enforces ML engine constraints. It verifies that the dataset reference exists, validates label directive integrity, and ensures the utterance count matrix maps correctly to integer values within acceptable bounds. The ML engine enforces a maximum of 100000 utterances per label to prevent memory exhaustion during vectorization.

Step 2: Duplicate Detection and File Size Verification

Before transmission, the uploader must verify that the attached dataset file does not exceed the platform maximum and that utterances are not duplicated. The following pipeline handles both checks.

type ValidationPipelineResult struct {
	IsDuplicate bool
	HasExceededSize bool
	ParsedUtterances int
	TotalLines int
}

func RunValidationPipeline(filePath string, payload UploadPayload) (ValidationPipelineResult, error) {
	const maxFileSize int64 = 50 * 1024 * 1024 // 50MB limit

	info, err := os.Stat(filePath)
	if err != nil {
		return ValidationPipelineResult{}, fmt.Errorf("failed to stat file: %w", err)
	}

	if info.Size() > maxFileSize {
		return ValidationPipelineResult{HasExceededSize: true}, nil
	}

	file, err := os.Open(filePath)
	if err != nil {
		return ValidationPipelineResult{}, fmt.Errorf("failed to open file: %w", err)
	}
	defer file.Close()

	seen := make(map[string]bool)
	scanner := bufio.NewScanner(file)
	var totalLines, parsedUtterances int
	var isDuplicate bool

	for scanner.Scan() {
		totalLines++
		line := strings.TrimSpace(scanner.Text())
		if line == "" {
			continue
		}

		if seen[line] {
			isDuplicate = true
			continue
		}
		seen[line] = true
		parsedUtterances++
	}

	if err := scanner.Err(); err != nil {
		return ValidationPipelineResult{}, fmt.Errorf("failed to read file: %w", err)
	}

	return ValidationPipelineResult{
		IsDuplicate:       isDuplicate,
		ParsedUtterances:  parsedUtterances,
		TotalLines:        totalLines,
	}, nil
}

The validation pipeline opens the dataset file, enforces the 50MB maximum file size limit, and scans each line to detect duplicates using a hash map. It returns structured metrics that the uploader uses to calculate data parsing success rates. The platform rejects files exceeding 50MB to prevent timeout failures during ingestion.

Step 3: Atomic POST with Retry Logic and Format Verification

The dataset transfer uses a single atomic POST operation. The request includes multipart form data for the file and a JSON metadata block. The implementation includes exponential backoff retry logic for 429 rate limit responses.

type UploadRequest struct {
	Endpoint    string
	Token       string
	Payload     UploadPayload
	FilePath    string
	AutoRetrain bool
}

func ExecuteAtomicUpload(req UploadRequest) (*http.Response, error) {
	client := &http.Client{Timeout: 60 * time.Second}
	maxRetries := 3

	for attempt := 0; attempt <= maxRetries; attempt++ {
		body := &bytes.Buffer{}
		writer := multipart.NewWriter(body)

		if err := writer.WriteField("metadata", string(payloadToJSON(req.Payload))); err != nil {
			return nil, fmt.Errorf("failed to write metadata field: %w", err)
		}

		file, err := os.Open(req.FilePath)
		if err != nil {
			return nil, fmt.Errorf("failed to open dataset file: %w", err)
		}

		part, err := writer.CreateFormFile("dataset", filepath.Base(req.FilePath))
		if err != nil {
			file.Close()
			return nil, fmt.Errorf("failed to create form file: %w", err)
		}

		if _, err := io.Copy(part, file); err != nil {
			file.Close()
			return nil, fmt.Errorf("failed to copy file to multipart: %w", err)
		}
		file.Close()

		if err := writer.Close(); err != nil {
			return nil, fmt.Errorf("failed to close multipart writer: %w", err)
		}

		query := ""
		if req.AutoRetrain {
			query = "?autoRetrain=true"
		}

		httpReq, err := http.NewRequest("POST", fmt.Sprintf("%s%s", req.Endpoint, query), body)
		if err != nil {
			return nil, fmt.Errorf("failed to create request: %w", err)
		}

		httpReq.Header.Set("Authorization", fmt.Sprintf("Bearer %s", req.Token))
		httpReq.Header.Set("Content-Type", writer.FormDataContentType())

		resp, err := client.Do(httpReq)
		if err != nil {
			return nil, fmt.Errorf("request failed: %w", err)
		}

		if resp.StatusCode == http.StatusTooManyRequests {
			backoff := time.Duration(attempt+1) * 2 * time.Second
			time.Sleep(backoff)
			continue
		}

		return resp, nil
	}

	return nil, fmt.Errorf("upload failed after %d retries due to rate limiting", maxRetries)
}

func payloadToJSON(p UploadPayload) []byte {
	data, _ := json.Marshal(p)
	return data
}

The ExecuteAtomicUpload function constructs a multipart POST request containing both the dataset file and the JSON metadata payload. It appends the ?autoRetrain=true query parameter when automatic model retraining is requested. The retry loop handles 429 responses with exponential backoff, preventing cascade failures during high-throughput ingestion.

Step 4: Webhook Synchronization, Metrics, and Audit Logging

The uploader must synchronize with external version control systems, track latency and parsing success rates, and generate structured audit logs. The following code implements these governance requirements.

type UploadMetrics struct {
	UploadLatencyMs     float64 `json:"uploadLatencyMs"`
	ParsingSuccessRate  float64 `json:"parsingSuccessRate"`
	Status              string  `json:"status"`
	DatasetID           string  `json:"datasetId"`
	Timestamp           string  `json:"timestamp"`
}

type AuditLog struct {
	Event   string        `json:"event"`
	Metrics UploadMetrics `json:"metrics"`
	Payload UploadPayload `json:"payload"`
}

func GenerateAuditLog(event string, metrics UploadMetrics, payload UploadPayload) {
	log, _ := json.Marshal(AuditLog{Event: event, Metrics: metrics, Payload: payload})
	fmt.Fprintln(os.Stdout, string(log))
}

func SyncWithVersionControl(webhookURL string, metrics UploadMetrics) error {
	payload, err := json.Marshal(metrics)
	if err != nil {
		return fmt.Errorf("failed to marshal webhook payload: %w", err)
	}

	req, err := http.NewRequest("POST", webhookURL, bytes.NewBuffer(payload))
	if err != nil {
		return fmt.Errorf("failed to create webhook request: %w", err)
	}
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{Timeout: 10 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("webhook request failed: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return fmt.Errorf("webhook sync failed with status %d", resp.StatusCode)
	}

	return nil
}

func CalculateParsingSuccessRate(result ValidationPipelineResult) float64 {
	if result.TotalLines == 0 {
		return 0.0
	}
	return float64(result.ParsedUtterances) / float64(result.TotalLines) * 100.0
}

The SyncWithVersionControl function posts structured metrics to an external webhook endpoint. The GenerateAuditLog function outputs JSON-lines formatted audit records to standard output for ML governance compliance. The CalculateParsingSuccessRate function derives the data quality metric used for model drift prevention.

Complete Working Example

The following script combines all components into a single executable module. Replace the placeholder credentials and endpoints before execution.

package main

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"
)

type OAuthTokenResponse struct {
	AccessToken string `json:"access_token"`
	TokenType   string `json:"token_type"`
	ExpiresIn   int    `json:"expires_in"`
}

type OAuthConfig struct {
	BaseURL   string
	ClientID  string
	Secret    string
}

type LabelDirective struct {
	Label    string `json:"label"`
	Type     string `json:"type"`
	Priority int    `json:"priority"`
}

type UploadPayload struct {
	DatasetIDRef      string           `json:"datasetIdReference"`
	UtteranceMatrix   json.RawMessage  `json:"utteranceCountMatrix"`
	LabelTaxonomy     []LabelDirective `json:"labelTaxonomyDirectives"`
	Metadata          map[string]string `json:"metadata"`
}

type ValidationPipelineResult struct {
	IsDuplicate       bool
	HasExceededSize   bool
	ParsedUtterances  int
	TotalLines        int
}

type UploadMetrics struct {
	UploadLatencyMs     float64 `json:"uploadLatencyMs"`
	ParsingSuccessRate  float64 `json:"parsingSuccessRate"`
	Status              string  `json:"status"`
	DatasetID           string  `json:"datasetId"`
	Timestamp           string  `json:"timestamp"`
}

type AuditLog struct {
	Event   string        `json:"event"`
	Metrics UploadMetrics `json:"metrics"`
	Payload UploadPayload `json:"payload"`
}

func FetchOAuthToken(cfg OAuthConfig) (string, error) {
	payload := fmt.Sprintf(
		"grant_type=client_credentials&client_id=%s&client_secret=%s&scope=cognigy:dataset:write cognigy:dataset:read cognigy:admin:retrain",
		cfg.ClientID, cfg.Secret,
	)

	req, err := http.NewRequest("POST", fmt.Sprintf("%s/oauth/token", cfg.BaseURL), bytes.NewBufferString(payload))
	if err != nil {
		return "", fmt.Errorf("failed to create oauth request: %w", err)
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	client := &http.Client{Timeout: 10 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return "", fmt.Errorf("oauth request failed: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return "", fmt.Errorf("oauth error %d: %s", resp.StatusCode, string(body))
	}

	var tokenResp OAuthTokenResponse
	if err := json.NewDecoder(resp.Body).Decode(&tokenResp); err != nil {
		return "", fmt.Errorf("failed to decode oauth response: %w", err)
	}

	return tokenResp.AccessToken, nil
}

func ValidateUploadSchema(payload UploadPayload) error {
	if payload.DatasetIDRef == "" {
		return fmt.Errorf("datasetIdReference is required")
	}
	if len(payload.LabelTaxonomy) == 0 {
		return fmt.Errorf("labelTaxonomyDirectives must contain at least one directive")
	}
	for _, directive := range payload.LabelTaxonomy {
		if directive.Label == "" || directive.Type == "" || directive.Priority < 0 {
			return fmt.Errorf("invalid label directive: missing label, type, or negative priority")
		}
	}
	var matrix map[string]int
	if err := json.Unmarshal(payload.UtteranceMatrix, &matrix); err != nil {
		return fmt.Errorf("utteranceCountMatrix must be a valid JSON object mapping labels to counts")
	}
	for label, count := range matrix {
		if count < 0 {
			return fmt.Errorf("utterance count for label %s cannot be negative", label)
		}
		if count > 100000 {
			return fmt.Errorf("utterance count for label %s exceeds ML engine limit of 100000", label)
		}
	}
	return nil
}

func RunValidationPipeline(filePath string) (ValidationPipelineResult, error) {
	const maxFileSize int64 = 50 * 1024 * 1024
	info, err := os.Stat(filePath)
	if err != nil {
		return ValidationPipelineResult{}, fmt.Errorf("failed to stat file: %w", err)
	}
	if info.Size() > maxFileSize {
		return ValidationPipelineResult{HasExceededSize: true}, nil
	}
	file, err := os.Open(filePath)
	if err != nil {
		return ValidationPipelineResult{}, fmt.Errorf("failed to open file: %w", err)
	}
	defer file.Close()
	seen := make(map[string]bool)
	scanner := bufio.NewScanner(file)
	var totalLines, parsedUtterances int
	var isDuplicate bool
	for scanner.Scan() {
		totalLines++
		line := strings.TrimSpace(scanner.Text())
		if line == "" {
			continue
		}
		if seen[line] {
			isDuplicate = true
			continue
		}
		seen[line] = true
		parsedUtterances++
	}
	if err := scanner.Err(); err != nil {
		return ValidationPipelineResult{}, fmt.Errorf("failed to read file: %w", err)
	}
	return ValidationPipelineResult{
		IsDuplicate:      isDuplicate,
		ParsedUtterances: parsedUtterances,
		TotalLines:       totalLines,
	}, nil
}

func ExecuteAtomicUpload(endpoint, token, filePath string, payload UploadPayload, autoRetrain bool) (*http.Response, error) {
	client := &http.Client{Timeout: 60 * time.Second}
	maxRetries := 3
	for attempt := 0; attempt <= maxRetries; attempt++ {
		body := &bytes.Buffer{}
		writer := multipart.NewWriter(body)
		metaBytes, _ := json.Marshal(payload)
		if err := writer.WriteField("metadata", string(metaBytes)); err != nil {
			return nil, fmt.Errorf("failed to write metadata field: %w", err)
		}
		file, err := os.Open(filePath)
		if err != nil {
			return nil, fmt.Errorf("failed to open dataset file: %w", err)
		}
		part, err := writer.CreateFormFile("dataset", filepath.Base(filePath))
		if err != nil {
			file.Close()
			return nil, fmt.Errorf("failed to create form file: %w", err)
		}
		if _, err := io.Copy(part, file); err != nil {
			file.Close()
			return nil, fmt.Errorf("failed to copy file to multipart: %w", err)
		}
		file.Close()
		if err := writer.Close(); err != nil {
			return nil, fmt.Errorf("failed to close multipart writer: %w", err)
		}
		query := ""
		if autoRetrain {
			query = "?autoRetrain=true"
		}
		httpReq, err := http.NewRequest("POST", fmt.Sprintf("%s%s", endpoint, query), body)
		if err != nil {
			return nil, fmt.Errorf("failed to create request: %w", err)
		}
		httpReq.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
		httpReq.Header.Set("Content-Type", writer.FormDataContentType())
		resp, err := client.Do(httpReq)
		if err != nil {
			return nil, fmt.Errorf("request failed: %w", err)
		}
		if resp.StatusCode == http.StatusTooManyRequests {
			backoff := time.Duration(attempt+1) * 2 * time.Second
			time.Sleep(backoff)
			continue
		}
		return resp, nil
	}
	return nil, fmt.Errorf("upload failed after %d retries due to rate limiting", maxRetries)
}

func SyncWithVersionControl(webhookURL string, metrics UploadMetrics) error {
	payload, err := json.Marshal(metrics)
	if err != nil {
		return fmt.Errorf("failed to marshal webhook payload: %w", err)
	}
	req, err := http.NewRequest("POST", webhookURL, bytes.NewBuffer(payload))
	if err != nil {
		return fmt.Errorf("failed to create webhook request: %w", err)
	}
	req.Header.Set("Content-Type", "application/json")
	client := &http.Client{Timeout: 10 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("webhook request failed: %w", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return fmt.Errorf("webhook sync failed with status %d", resp.StatusCode)
	}
	return nil
}

func GenerateAuditLog(event string, metrics UploadMetrics, payload UploadPayload) {
	log, _ := json.Marshal(AuditLog{Event: event, Metrics: metrics, Payload: payload})
	fmt.Fprintln(os.Stdout, string(log))
}

func CalculateParsingSuccessRate(result ValidationPipelineResult) float64 {
	if result.TotalLines == 0 {
		return 0.0
	}
	return float64(result.ParsedUtterances) / float64(result.TotalLines) * 100.0
}

func main() {
	// Configuration
	apiBase := "https://your-instance.cognigy.ai/api/v1"
	webhookURL := "https://your-vcs-webhook.example.com/sync"
	filePath := "training_dataset.txt"
	autoRetrain := true

	// Authentication
	token, err := FetchOAuthToken(OAuthConfig{
		BaseURL:  apiBase,
		ClientID: "YOUR_CLIENT_ID",
		Secret:   "YOUR_CLIENT_SECRET",
	})
	if err != nil {
		fmt.Fprintf(os.Stderr, "Authentication failed: %v\n", err)
		os.Exit(1)
	}

	// Payload Construction
	payload := UploadPayload{
		DatasetIDRef: "ds_prod_intent_v2",
		UtteranceMatrix: json.RawMessage(`{"greeting": 150, "complaint": 320, "order_status": 200}`),
		LabelTaxonomy: []LabelDirective{
			{Label: "greeting", Type: "intent", Priority: 1},
			{Label: "complaint", Type: "intent", Priority: 2},
			{Label: "order_status", Type: "intent", Priority: 1},
		},
		Metadata: map[string]string{"version": "2.1.0", "source": "automated_pipeline"},
	}

	if err := ValidateUploadSchema(payload); err != nil {
		fmt.Fprintf(os.Stderr, "Schema validation failed: %v\n", err)
		os.Exit(1)
	}

	// Validation Pipeline
	valResult, err := RunValidationPipeline(filePath)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Validation pipeline failed: %v\n", err)
		os.Exit(1)
	}
	if valResult.HasExceededSize {
		fmt.Fprintf(os.Stderr, "File exceeds 50MB limit\n")
		os.Exit(1)
	}

	// Atomic Upload
	startTime := time.Now()
	resp, err := ExecuteAtomicUpload(fmt.Sprintf("%s/datasets/upload", apiBase), token, filePath, payload, autoRetrain)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Upload failed: %v\n", err)
		os.Exit(1)
	}
	defer resp.Body.Close()

	latency := time.Since(startTime).Seconds() * 1000
	status := "failed"
	if resp.StatusCode >= 200 && resp.StatusCode < 300 {
		status = "success"
	}

	metrics := UploadMetrics{
		UploadLatencyMs:    latency,
		ParsingSuccessRate: CalculateParsingSuccessRate(valResult),
		Status:             status,
		DatasetID:          payload.DatasetIDRef,
		Timestamp:          time.Now().UTC().Format(time.RFC3339),
	}

	// Audit Logging
	GenerateAuditLog("dataset_upload_complete", metrics, payload)

	// Version Control Sync
	if err := SyncWithVersionControl(webhookURL, metrics); err != nil {
		fmt.Fprintf(os.Stderr, "Webhook sync failed: %v\n", err)
	}

	if status == "success" {
		fmt.Println("Dataset uploaded and model retraining triggered successfully.")
	} else {
		fmt.Printf("Upload completed with status %d\n", resp.StatusCode)
	}
}

Common Errors & Debugging

Error: 400 Bad Request

  • Cause: The JSON metadata payload violates schema constraints, or the multipart form data is malformed.
  • Fix: Verify that datasetIdReference matches an existing dataset, ensure utteranceCountMatrix contains valid integers, and confirm that labelTaxonomyDirectives contains at least one entry. Check the ValidateUploadSchema function output before transmission.

Error: 401 Unauthorized

  • Cause: The OAuth token is expired, malformed, or missing required scopes.
  • Fix: Regenerate the token using FetchOAuthToken. Verify that the client credentials possess cognigy:dataset:write and cognigy:admin:retrain scopes. Implement token caching with automatic refresh before expires_in elapses.

Error: 403 Forbidden

  • Cause: The authenticated client lacks permission to modify the target dataset or trigger model retraining.
  • Fix: Assign the cognigy:admin:retrain scope to the OAuth client. Confirm that the dataset ID reference belongs to a workspace accessible by the client credentials.

Error: 413 Payload Too Large

  • Cause: The attached dataset file exceeds the 50MB platform limit.
  • Fix: The RunValidationPipeline function pre-checks file size. Split large datasets into smaller chunks or compress the file before upload. The platform enforces this limit to prevent ingestion timeouts.

Error: 429 Too Many Requests

  • Cause: The API rate limit is exceeded during high-throughput uploads.
  • Fix: The ExecuteAtomicUpload function implements exponential backoff retry logic. If failures persist, reduce concurrent upload threads or implement a request queue with token bucket rate limiting.

Error: 500 Internal Server Error

  • Cause: ML engine ingestion failure due to corrupted utterance format or unsupported encoding.
  • Fix: Verify that the dataset file uses UTF-8 encoding without BOM. Ensure each line contains a single utterance without control characters. Check the platform ingestion logs for vectorization errors.

Official References