Documentation Index
Fetch the complete documentation index at: https://docs.dakota.xyz/llms.txt
Use this file to discover all available pages before exploring further.
Common authentication issues and their solutions.
HTTP Status Codes
401 Unauthorized
Symptoms:
- Request returns
401 Unauthorized
- Error message indicates authentication failure
Common Causes:
Missing or Invalid API Key
{
"type": "https://docs.dakota.xyz/errors/authentication-error",
"title": "Unauthorized",
"status": 401,
"detail": "Missing or invalid API key",
"instance": "/customers",
"request_id": "req_abc123"
}
Solutions:
- Verify your API key is exactly 60 characters
- Check that you’re including the
x-api-key header
- Ensure no extra whitespace or characters in the key
# ✅ Correct format
curl -X GET https://api.platform.dakota.xyz/customers \
-H "x-api-key: AHGlPZaxDSMz8Wf1l8VRH4ObdbHiKsWFWnmRyHtiwAc="
# ❌ Common mistakes
-H "x-api-key: AHGlPZaxDSMz8Wf1l8VRH4ObdbHiKsWFWnmRyHtiwAc= " # extra spaces
-H "API-Key: AHGlPZaxDSMz8Wf1l8VRH4ObdbHiKsWFWnmRyHtiwAc=" # wrong header name
// ✅ Correct format
const headers = {
'x-api-key': 'AHGlPZaxDSMz8Wf1l8VRH4ObdbHiKsWFWnmRyHtiwAc='
};
// ❌ Common mistakes
const headers = {
'x-api-key': ' AHGlPZaxDSMz8Wf1l8VRH4ObdbHiKsWFWnmRyHtiwAc= ', // extra spaces
'API-Key': 'AHGlPZaxDSMz8Wf1l8VRH4ObdbHiKsWFWnmRyHtiwAc=' // wrong header name
};
# ✅ Correct format
headers = {
'x-api-key': 'AHGlPZaxDSMz8Wf1l8VRH4ObdbHiKsWFWnmRyHtiwAc='
}
# ❌ Common mistakes
headers = {
'x-api-key': ' AHGlPZaxDSMz8Wf1l8VRH4ObdbHiKsWFWnmRyHtiwAc= ', # extra spaces
'API-Key': 'AHGlPZaxDSMz8Wf1l8VRH4ObdbHiKsWFWnmRyHtiwAc=' # wrong header name
}
// ✅ Correct format
headers := map[string]string{
"x-api-key": "AHGlPZaxDSMz8Wf1l8VRH4ObdbHiKsWFWnmRyHtiwAc=",
}
// ❌ Common mistakes
headers := map[string]string{
"x-api-key": " AHGlPZaxDSMz8Wf1l8VRH4ObdbHiKsWFWnmRyHtiwAc= ", // extra spaces
"API-Key": "AHGlPZaxDSMz8Wf1l8VRH4ObdbHiKsWFWnmRyHtiwAc=", // wrong header name
}
use reqwest::header::{HeaderMap, HeaderValue};
// ✅ Correct format
let mut headers = HeaderMap::new();
headers.insert("x-api-key", HeaderValue::from_str("AHGlPZaxDSMz8Wf1l8VRH4ObdbHiKsWFWnmRyHtiwAc=").unwrap());
// ❌ Common mistakes - extra spaces or wrong header name will cause authentication failures
// ✅ Correct format
Map<String, String> headers = new HashMap<>();
headers.put("x-api-key", "AHGlPZaxDSMz8Wf1l8VRH4ObdbHiKsWFWnmRyHtiwAc=");
// ❌ Common mistakes
headers.put("x-api-key", " AHGlPZaxDSMz8Wf1l8VRH4ObdbHiKsWFWnmRyHtiwAc= "); // extra spaces
headers.put("API-Key", "AHGlPZaxDSMz8Wf1l8VRH4ObdbHiKsWFWnmRyHtiwAc="); // wrong header name
Deleted or Expired API Key
Solution: Create a new API key in your Dakota Platform dashboard
Wrong Environment
Solution: Ensure you’re using the correct base URL:
- Production:
https://api.platform.dakota.xyz
403 Forbidden
Symptoms:
- Request returns
403 Forbidden
- API key is valid but access is denied
Common Causes:
Insufficient Permissions
{
"type": "https://docs.dakota.xyz/errors/forbidden",
"title": "Forbidden",
"status": 403,
"detail": "API key lacks required permissions for this endpoint",
"instance": "/customers",
"request_id": "req_abc123"
}
Solutions:
- Check if your account has access to the requested feature
- Verify API key permissions in the Dakota Platform dashboard
- Contact support if you need additional permissions
Account Limitations
Solutions:
- Complete required account verification steps
- Upgrade your account plan if needed
- Contact support for account-specific limitations
429 Too Many Requests
Symptoms:
- Request returns
429 Too Many Requests
- No response body, only HTTP status
- Rate limit headers indicate limits exceeded
Response Headers:
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1640995290
Retry-After: 30
Solutions:
- Implement exponential backoff (see Rate Limiting guide)
- Check
Retry-After header for seconds to wait before retrying
- Distribute requests more evenly over time
- Contact support if you need higher rate limits
Missing x-idempotency-key for POST Requests
Error:
{
"type": "https://docs.dakota.xyz/errors/validation-error",
"title": "Validation Error",
"status": 400,
"detail": "x-idempotency-key header is required for POST requests",
"instance": "/customers",
"request_id": "req_abc123"
}
Solution:
Include a unique UUID in the x-idempotency-key header for POST requests only:
# ✅ POST request with idempotency key
curl -X POST https://api.platform.dakota.xyz/customers \
-H "x-api-key: your-api-key" \
-H "x-idempotency-key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"customer_type": "business", "name": "Acme Corp"}'
# ✅ GET request without idempotency key
curl -X GET https://api.platform.dakota.xyz/customers \
-H "x-api-key: your-api-key"
// ✅ POST request with idempotency key
fetch('https://api.platform.dakota.xyz/customers', {
method: 'POST',
headers: {
'x-api-key': 'your-api-key',
'x-idempotency-key': crypto.randomUUID(),
'Content-Type': 'application/json'
},
body: JSON.stringify({customer_type: 'business', name: 'Acme Corp'})
});
// ✅ GET request without idempotency key
fetch('https://api.platform.dakota.xyz/customers', {
headers: {
'x-api-key': 'your-api-key'
}
});
import requests
import uuid
# ✅ POST request with idempotency key
response = requests.post(
'https://api.platform.dakota.xyz/customers',
headers={
'x-api-key': 'your-api-key',
'x-idempotency-key': str(uuid.uuid4()),
'Content-Type': 'application/json'
},
json={'customer_type': 'business', 'name': 'Acme Corp'}
)
# ✅ GET request without idempotency key
response = requests.get(
'https://api.platform.dakota.xyz/customers',
headers={'x-api-key': 'your-api-key'}
)
package main
import (
"bytes"
"encoding/json"
"net/http"
"github.com/google/uuid"
)
// ✅ POST request with idempotency key
data := map[string]interface{}{
"customer_type": "business",
"name": "Acme Corp",
}
jsonData, _ := json.Marshal(data)
req, _ := http.NewRequest("POST", "https://api.platform.dakota.xyz/customers", bytes.NewBuffer(jsonData))
req.Header.Set("x-api-key", "your-api-key")
req.Header.Set("x-idempotency-key", uuid.New().String())
req.Header.Set("Content-Type", "application/json")
// ✅ GET request without idempotency key
req, _ = http.NewRequest("GET", "https://api.platform.dakota.xyz/customers", nil)
req.Header.Set("x-api-key", "your-api-key")
use reqwest::header::{HeaderMap, HeaderValue};
use serde_json::json;
use uuid::Uuid;
// ✅ POST request with idempotency key
let mut headers = HeaderMap::new();
headers.insert("x-api-key", HeaderValue::from_str("your-api-key").unwrap());
headers.insert("x-idempotency-key", HeaderValue::from_str(&Uuid::new_v4().to_string()).unwrap());
headers.insert("Content-Type", HeaderValue::from_static("application/json"));
let data = json!({
"customer_type": "business",
"name": "Acme Corp"
});
let client = reqwest::Client::new();
let response = client
.post("https://api.platform.dakota.xyz/customers")
.headers(headers)
.json(&data)
.send()
.await?;
// ✅ GET request without idempotency key
let mut headers = HeaderMap::new();
headers.insert("x-api-key", HeaderValue::from_str("your-api-key").unwrap());
let response = client
.get("https://api.platform.dakota.xyz/customers")
.headers(headers)
.send()
.await?;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.URI;
import java.util.UUID;
// ✅ POST request with idempotency key
String requestBody = """
{
"customer_type": "business",
"name": "Acme Corp"
}
""";
HttpRequest postRequest = HttpRequest.newBuilder()
.uri(URI.create("https://api.platform.dakota.xyz/customers"))
.header("x-api-key", "your-api-key")
.header("x-idempotency-key", UUID.randomUUID().toString())
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
// ✅ GET request without idempotency key
HttpRequest getRequest = HttpRequest.newBuilder()
.uri(URI.create("https://api.platform.dakota.xyz/customers"))
.header("x-api-key", "your-api-key")
.GET()
.build();
Error:
{
"type": "https://docs.dakota.xyz/errors/validation-error",
"title": "Validation Error",
"status": 400,
"detail": "x-idempotency-key must be a valid UUID",
"instance": "/customers",
"request_id": "req_abc123"
}
Solution:
Use a properly formatted UUID:
# ✅ Valid UUID formats
$(uuidgen) # System command
'550e8400-e29b-41d4-a716-446655440000' # Manual UUID
# ❌ Invalid formats
'123'
'not-a-uuid'
'550e8400e29b41d4a716446655440000' # Missing hyphens
// ✅ Valid UUID formats
'550e8400-e29b-41d4-a716-446655440000'
crypto.randomUUID() // Browser
require('uuid').v4() // Node.js
// ❌ Invalid formats
'123'
'not-a-uuid'
'550e8400e29b41d4a716446655440000' // Missing hyphens
import uuid
# ✅ Valid UUID formats
str(uuid.uuid4()) # Standard library
'550e8400-e29b-41d4-a716-446655440000' # Manual UUID
# ❌ Invalid formats
'123'
'not-a-uuid'
'550e8400e29b41d4a716446655440000' # Missing hyphens
import "github.com/google/uuid"
// ✅ Valid UUID formats
uuid.New().String() // Google UUID library
"550e8400-e29b-41d4-a716-446655440000" // Manual UUID
// ❌ Invalid formats
"123"
"not-a-uuid"
"550e8400e29b41d4a716446655440000" // Missing hyphens
use uuid::Uuid;
// ✅ Valid UUID formats
Uuid::new_v4().to_string() // UUID crate
"550e8400-e29b-41d4-a716-446655440000" // Manual UUID
// ❌ Invalid formats
"123"
"not-a-uuid"
"550e8400e29b41d4a716446655440000" // Missing hyphens
import java.util.UUID;
// ✅ Valid UUID formats
UUID.randomUUID().toString() // Standard library
"550e8400-e29b-41d4-a716-446655440000" // Manual UUID
// ❌ Invalid formats
"123"
"not-a-uuid"
"550e8400e29b41d4a716446655440000" // Missing hyphens
Connection Issues
SSL/TLS Errors
Symptoms:
- Connection fails with SSL certificate errors
- “Unable to verify SSL certificate” messages
Solutions:
# ✅ Certificate validation enabled (default)
curl -X GET https://api.platform.dakota.xyz/customers \
-H "x-api-key: your-api-key"
# If you have custom certificates
curl --cacert /path/to/certificate.pem \
-X GET https://api.platform.dakota.xyz/customers \
-H "x-api-key: your-api-key"
// ✅ Certificate validation is handled by the browser/Node.js
const https = require('https');
const agent = new https.Agent({
rejectUnauthorized: true // Default, but make it explicit
});
fetch(url, { agent }); // Node.js only
import requests
# ✅ Certificate validation enabled (default)
response = requests.get(url, verify=True)
# If you have custom certificates
response = requests.get(url, verify='/path/to/certificate.pem')
import (
"crypto/tls"
"net/http"
)
// ✅ Certificate validation enabled (default)
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: false, // Default
},
},
}
// ✅ Certificate validation enabled by default
let client = reqwest::Client::builder()
.danger_accept_invalid_certs(false) // Default
.build()?;
import javax.net.ssl.SSLContext;
// ✅ Certificate validation enabled by default
HttpClient client = HttpClient.newBuilder()
.sslContext(SSLContext.getDefault())
.build();
Network Timeouts
Solutions:
# Set timeout values
curl --max-time 30 \
-X GET https://api.platform.dakota.xyz/customers \
-H "x-api-key: your-api-key"
// Note: fetch() doesn't support timeout directly, use AbortController
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 30000);
try {
const response = await fetch(url, {
headers: { 'x-api-key': apiKey },
signal: controller.signal
});
clearTimeout(timeoutId);
} catch (error) {
clearTimeout(timeoutId);
}
import requests
response = requests.get(
url,
headers={'x-api-key': api_key},
timeout=30 # 30 seconds
)
import (
"context"
"net/http"
"time"
)
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
req.Header.Set("x-api-key", apiKey)
client := &http.Client{}
resp, err := client.Do(req)
use std::time::Duration;
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let response = client
.get(url)
.header("X-API-Key", api_key)
.send()
.await?;
import java.time.Duration;
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(30))
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.timeout(Duration.ofSeconds(30))
.header("X-API-Key", apiKey)
.GET()
.build();
Debugging Steps
Check your API key meets the requirements:
# Check API key length
echo "${#DAKOTA_API_KEY}" # Should output 60
# Basic validation
if [ ${#DAKOTA_API_KEY} -ne 60 ]; then
echo "Error: API key must be exactly 60 characters"
fi
function validateApiKey(apiKey) {
if (!apiKey) {
throw new Error('API key is required');
}
if (apiKey.length !== 60) {
throw new Error(`API key must be exactly 60 characters, got ${apiKey.length}`);
}
// Check if it's base64 encoded
const base64Regex = /^[A-Za-z0-9+/]+=*$/;
if (!base64Regex.test(apiKey)) {
throw new Error('API key must be base64 encoded');
}
return true;
}
import re
import base64
def validate_api_key(api_key):
if not api_key:
raise ValueError('API key is required')
if len(api_key) != 60:
raise ValueError(f'API key must be exactly 60 characters, got {len(api_key)}')
# Check if it's base64 encoded
base64_regex = re.compile(r'^[A-Za-z0-9+/]+=*$')
if not base64_regex.match(api_key):
raise ValueError('API key must be base64 encoded')
return True
import (
"encoding/base64"
"fmt"
"regexp"
)
func validateAPIKey(apiKey string) error {
if apiKey == "" {
return fmt.Errorf("API key is required")
}
if len(apiKey) != 60 {
return fmt.Errorf("API key must be exactly 60 characters, got %d", len(apiKey))
}
// Check if it's base64 encoded
base64Regex := regexp.MustCompile(`^[A-Za-z0-9+/]+=*$`)
if !base64Regex.MatchString(apiKey) {
return fmt.Errorf("API key must be base64 encoded")
}
return nil
}
use regex::Regex;
fn validate_api_key(api_key: &str) -> Result<bool, String> {
if api_key.is_empty() {
return Err("API key is required".to_string());
}
if api_key.len() != 60 {
return Err(format!(
"API key must be exactly 60 characters, got {}",
api_key.len()
));
}
// Check if it's base64 encoded
let base64_regex = Regex::new(r"^[A-Za-z0-9+/]+=*$").unwrap();
if !base64_regex.is_match(api_key) {
return Err("API key must be base64 encoded".to_string());
}
Ok(true)
}
import java.util.regex.Pattern;
public class APIKeyValidator {
private static final Pattern BASE64_PATTERN =
Pattern.compile("^[A-Za-z0-9+/]+=*$");
public static boolean validateApiKey(String apiKey) throws IllegalArgumentException {
if (apiKey == null || apiKey.isEmpty()) {
throw new IllegalArgumentException("API key is required");
}
if (apiKey.length() != 60) {
throw new IllegalArgumentException(
String.format("API key must be exactly 60 characters, got %d", apiKey.length())
);
}
// Check if it's base64 encoded
if (!BASE64_PATTERN.matcher(apiKey).matches()) {
throw new IllegalArgumentException("API key must be base64 encoded");
}
return true;
}
}
2. Test with cURL
Use cURL to isolate issues from your code:
# Test GET request
curl -v -X GET https://api.platform.dakota.xyz/customers \
-H "x-api-key: YOUR_API_KEY"
# Test POST request
curl -v -X POST https://api.platform.dakota.xyz/customers \
-H "x-api-key: YOUR_API_KEY" \
-H "x-idempotency-key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"customer_type": "business", "name": "Test Company"}'
The -v flag provides verbose output showing the full HTTP exchange.
Always inspect response headers for debugging information:
# Use -v for verbose output including headers
curl -v -X GET https://api.platform.dakota.xyz/customers \
-H "x-api-key: YOUR_API_KEY"
# Use -i to include response headers in output
curl -i -X GET https://api.platform.dakota.xyz/customers \
-H "x-api-key: YOUR_API_KEY"
async function debugRequest(url, options) {
const response = await fetch(url, options);
console.log('Status:', response.status);
console.log('Headers:');
response.headers.forEach((value, key) => {
console.log(` ${key}: ${value}`);
});
const body = await response.text();
console.log('Body:', body);
return response;
}
import requests
def debug_request(url, **kwargs):
response = requests.request(**kwargs, url=url)
print(f'Status: {response.status_code}')
print('Headers:')
for key, value in response.headers.items():
print(f' {key}: {value}')
print(f'Body: {response.text}')
return response
import (
"fmt"
"io"
"net/http"
"net/http/httputil"
)
func debugRequest(req *http.Request) (*http.Response, error) {
// Dump the request
reqDump, _ := httputil.DumpRequestOut(req, true)
fmt.Printf("REQUEST:\n%s\n", reqDump)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
// Dump the response
respDump, _ := httputil.DumpResponse(resp, true)
fmt.Printf("RESPONSE:\n%s\n", respDump)
return resp, nil
}
use reqwest::Response;
async fn debug_request(response: Response) {
println!("Status: {}", response.status());
println!("Headers:");
for (key, value) in response.headers() {
println!(" {}: {:?}", key, value);
}
let body = response.text().await.unwrap_or_default();
println!("Body: {}", body);
}
import java.net.http.HttpResponse;
public void debugRequest(HttpResponse<String> response) {
System.out.printf("Status: %d%n", response.statusCode());
System.out.println("Headers:");
response.headers().map().forEach((key, values) -> {
values.forEach(value -> {
System.out.printf(" %s: %s%n", key, value);
});
});
System.out.printf("Body: %s%n", response.body());
}
4. Enable Request Logging
Log your requests to identify issues:
# Log to file for analysis
curl -v -X GET https://api.platform.dakota.xyz/customers \
-H "x-api-key: YOUR_API_KEY" \
2>&1 | tee request.log
# Remove sensitive data from logs
sed -i 's/x-api-key: .*/x-api-key: [REDACTED]/g' request.log
function logRequest(url, options) {
const safeHeaders = { ...options.headers };
delete safeHeaders['x-api-key']; // Don't log sensitive data
console.log('Making request:', {
url,
method: options.method || 'GET',
headers: safeHeaders,
bodyLength: options.body ? options.body.length : 0
});
}
import logging
from urllib.parse import urlparse
def log_request(method, url, headers, body=None):
safe_headers = headers.copy()
if 'x-api-key' in safe_headers:
safe_headers['x-api-key'] = '[REDACTED]'
parsed_url = urlparse(url)
logging.info('Making request: %s', {
'method': method,
'url': f"{parsed_url.scheme}://{parsed_url.netloc}{parsed_url.path}",
'headers': safe_headers,
'body_length': len(body) if body else 0
})
import (
"log"
"net/url"
)
func logRequest(method, urlStr string, headers map[string]string, bodyLength int) {
safeHeaders := make(map[string]string)
for k, v := range headers {
if k == "x-api-key" {
safeHeaders[k] = "[REDACTED]"
} else {
safeHeaders[k] = v
}
}
parsedURL, _ := url.Parse(urlStr)
log.Printf("Making request: method=%s url=%s://%s%s headers=%v bodyLength=%d",
method,
parsedURL.Scheme,
parsedURL.Host,
parsedURL.Path,
safeHeaders,
bodyLength,
)
}
use std::collections::HashMap;
use log::info;
use url::Url;
fn log_request(method: &str, url: &str, headers: &HashMap<String, String>, body_length: usize) {
let mut safe_headers = headers.clone();
if safe_headers.contains_key("x-api-key") {
safe_headers.insert("x-api-key".to_string(), "[REDACTED]".to_string());
}
if let Ok(parsed_url) = Url::parse(url) {
info!(
"Making request: method={} url={}://{}{} headers={:?} body_length={}",
method,
parsed_url.scheme(),
parsed_url.host_str().unwrap_or(""),
parsed_url.path(),
safe_headers,
body_length
);
}
}
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
public class RequestLogger {
private static final Logger logger = Logger.getLogger(RequestLogger.class.getName());
public static void logRequest(String method, String url, Map<String, String> headers, int bodyLength) {
Map<String, String> safeHeaders = new HashMap<>(headers);
if (safeHeaders.containsKey("x-api-key")) {
safeHeaders.put("x-api-key", "[REDACTED]");
}
try {
URI uri = URI.create(url);
logger.info(String.format(
"Making request: method=%s url=%s://%s%s headers=%s bodyLength=%d",
method,
uri.getScheme(),
uri.getHost(),
uri.getPath(),
safeHeaders,
bodyLength
));
} catch (Exception e) {
logger.warning("Failed to parse URL for logging: " + url);
}
}
}
Error Response Format
All Dakota Platform API errors follow RFC 9457 Problem Details format with application/problem+json content type:
{
"type": "https://docs.dakota.xyz/errors/authentication-error",
"title": "Unauthorized",
"status": 401,
"detail": "Missing or invalid API key",
"instance": "/customers",
"request_id": "req_abc123"
}
Common error types (the type field URI):
https://docs.dakota.xyz/errors/authentication-error - Authentication failed (401)
https://docs.dakota.xyz/errors/forbidden - Access denied (403)
https://docs.dakota.xyz/errors/validation-error - Invalid request format (400)
https://docs.dakota.xyz/errors/not-found - Resource doesn’t exist (404)
https://docs.dakota.xyz/errors/rate-limited - Too many requests (429)
https://docs.dakota.xyz/errors/internal-error - Server error (500)
Rate limiting (429) also returns RFC 9457 Problem Details:
{
"type": "https://docs.dakota.xyz/errors/rate-limited",
"title": "Rate Limited",
"status": 429,
"detail": "Too many requests. Please retry later.",
"instance": "/customers",
"request_id": "req_xyz789"
}
Getting Help
If you’re still experiencing issues:
- Check the API status page for any ongoing issues
- Review recent changes to your code or configuration
- Test with minimal examples to isolate the problem
- Contact support with:
- Complete error messages
- Request/response logs (with API keys removed)
- Steps to reproduce the issue
- A relevant Request ID from the response headers, if available
- Email: support@dakota.xyz
- Include “API Authentication Issue” in the subject line
- Provide relevant logs with sensitive information removed
- Mention this troubleshooting guide and what you’ve already tried
Quick Checklist
Before contacting support, verify: