Skip to main content

Code Examples

This page provides complete workflow examples for common Soku API tasks. Each example is shown in curl, JavaScript (Node.js), and Python to help you get started quickly.

Setup

Environment Variable

All examples assume your API key is stored in an environment variable:
export SOKU_API_KEY="sk_live_your_api_key_here"

JavaScript Base Configuration

The JavaScript examples use the built-in fetch API available in Node.js 18+. Here is a reusable helper function used throughout this page:
const SOKU_API_KEY = process.env.SOKU_API_KEY;
const BASE_URL = 'https://api.mysoku.io';

async function sokuRequest(path, options = {}) {
  const url = `${BASE_URL}${path}`;
  const headers = {
    'Content-Type': 'application/json',
    'soku-api-key': SOKU_API_KEY,
    ...options.headers,
  };

  const response = await fetch(url, {
    ...options,
    headers,
  });

  if (!response.ok) {
    const body = await response.json();
    const error = new Error(body.error?.message || 'API request failed');
    error.code = body.error?.code;
    error.status = response.status;
    error.requestId = body.error?.requestId;
    throw error;
  }

  // Handle 204 No Content
  if (response.status === 204) {
    return null;
  }

  return response.json();
}

Python Base Configuration

The Python examples use the requests library. Install it with pip install requests.
import os
import requests

SOKU_API_KEY = os.environ["SOKU_API_KEY"]
BASE_URL = "https://api.mysoku.io"

def soku_request(path, method="GET", json_data=None, extra_headers=None):
    url = f"{BASE_URL}{path}"
    headers = {
        "Content-Type": "application/json",
        "soku-api-key": SOKU_API_KEY,
    }
    if extra_headers:
        headers.update(extra_headers)

    response = requests.request(method, url, json=json_data, headers=headers)

    if not response.ok:
        body = response.json()
        error_info = body.get("error", {})
        raise Exception(
            f"API error {error_info.get('code')}: {error_info.get('message')} "
            f"(requestId: {error_info.get('requestId')})"
        )

    if response.status_code == 204:
        return None

    return response.json()

Publish a Text Post

Post a text update to multiple platforms at once.

curl

curl -X POST https://api.mysoku.io/v1/posts \
  -H "Content-Type: application/json" \
  -H "soku-api-key: $SOKU_API_KEY" \
  -d '{
    "post": {
      "content": {
        "text": "Just shipped our biggest update yet. More details coming soon.",
        "mediaType": "text",
        "platform": ["threads", "x", "linkedin"]
      }
    }
  }'

JavaScript

async function publishTextPost() {
  const result = await sokuRequest('/v1/posts', {
    method: 'POST',
    body: JSON.stringify({
      post: {
        content: {
          text: 'Just shipped our biggest update yet. More details coming soon.',
          mediaType: 'text',
          platform: ['threads', 'x', 'linkedin'],
        },
      },
    }),
  });

  console.log('Post submitted:', result.postSubmissionId);
  return result;
}

Python

def publish_text_post():
    result = soku_request("/v1/posts", method="POST", json_data={
        "post": {
            "content": {
                "text": "Just shipped our biggest update yet. More details coming soon.",
                "mediaType": "text",
                "platform": ["threads", "x", "linkedin"],
            }
        }
    })

    print(f"Post submitted: {result['postSubmissionId']}")
    return result

Upload Media and Publish a Video Post

Upload a video from a remote URL, then publish it to multiple platforms.

curl

# Step 1: Upload the video
MEDIA_RESPONSE=$(curl -s -X POST https://api.mysoku.io/v1/media \
  -H "Content-Type: application/json" \
  -H "soku-api-key: $SOKU_API_KEY" \
  -d '{
    "url": "https://example.com/videos/product-demo.mp4"
  }')

MEDIA_URL=$(echo "$MEDIA_RESPONSE" | jq -r '.url')
echo "Uploaded media: $MEDIA_URL"

# Step 2: Publish the video post
curl -X POST https://api.mysoku.io/v1/posts \
  -H "Content-Type: application/json" \
  -H "soku-api-key: $SOKU_API_KEY" \
  -d "{
    \"post\": {
      \"content\": {
        \"text\": \"Watch our full product walkthrough\",
        \"mediaType\": \"video\",
        \"videoUrl\": \"$MEDIA_URL\",
        \"platform\": [
          {\"platform\": \"instagram\", \"accountId\": \"ig_main\"},
          {\"platform\": \"tiktok\", \"accountId\": \"tt_brand\"},
          \"youtube\"
        ]
      }
    }
  }"

JavaScript

async function uploadAndPublishVideo() {
  // Step 1: Upload the video
  const media = await sokuRequest('/v1/media', {
    method: 'POST',
    body: JSON.stringify({
      url: 'https://example.com/videos/product-demo.mp4',
    }),
  });

  console.log('Uploaded media:', media.url);

  // Step 2: Publish the video post
  const result = await sokuRequest('/v1/posts', {
    method: 'POST',
    body: JSON.stringify({
      post: {
        content: {
          text: 'Watch our full product walkthrough',
          mediaType: 'video',
          videoUrl: media.url,
          platform: [
            { platform: 'instagram', accountId: 'ig_main' },
            { platform: 'tiktok', accountId: 'tt_brand' },
            'youtube',
          ],
        },
      },
    }),
  });

  console.log('Post submitted:', result.postSubmissionId);
  return result;
}

Python

def upload_and_publish_video():
    # Step 1: Upload the video
    media = soku_request("/v1/media", method="POST", json_data={
        "url": "https://example.com/videos/product-demo.mp4"
    })

    print(f"Uploaded media: {media['url']}")

    # Step 2: Publish the video post
    result = soku_request("/v1/posts", method="POST", json_data={
        "post": {
            "content": {
                "text": "Watch our full product walkthrough",
                "mediaType": "video",
                "videoUrl": media["url"],
                "platform": [
                    {"platform": "instagram", "accountId": "ig_main"},
                    {"platform": "tiktok", "accountId": "tt_brand"},
                    "youtube",
                ],
            }
        }
    })

    print(f"Post submitted: {result['postSubmissionId']}")
    return result

Publish an Image Post with Multiple Images

curl

curl -X POST https://api.mysoku.io/v1/posts \
  -H "Content-Type: application/json" \
  -H "soku-api-key: $SOKU_API_KEY" \
  -d '{
    "post": {
      "content": {
        "text": "Behind the scenes from today'\''s shoot",
        "mediaType": "image",
        "imageUrls": [
          "https://storage.mysoku.io/media/img1.jpg",
          "https://storage.mysoku.io/media/img2.jpg",
          "https://storage.mysoku.io/media/img3.jpg"
        ],
        "platform": [
          { "platform": "instagram", "accountId": "ig_main" },
          { "platform": "facebook", "accountId": "fb_page" },
          "linkedin"
        ]
      }
    }
  }'

JavaScript

async function publishImagePost() {
  const result = await sokuRequest('/v1/posts', {
    method: 'POST',
    body: JSON.stringify({
      post: {
        content: {
          text: "Behind the scenes from today's shoot",
          mediaType: 'image',
          imageUrls: [
            'https://storage.mysoku.io/media/img1.jpg',
            'https://storage.mysoku.io/media/img2.jpg',
            'https://storage.mysoku.io/media/img3.jpg',
          ],
          platform: [
            { platform: 'instagram', accountId: 'ig_main' },
            { platform: 'facebook', accountId: 'fb_page' },
            'linkedin',
          ],
        },
      },
    }),
  });

  console.log('Post submitted:', result.postSubmissionId);
  return result;
}

Python

def publish_image_post():
    result = soku_request("/v1/posts", method="POST", json_data={
        "post": {
            "content": {
                "text": "Behind the scenes from today's shoot",
                "mediaType": "image",
                "imageUrls": [
                    "https://storage.mysoku.io/media/img1.jpg",
                    "https://storage.mysoku.io/media/img2.jpg",
                    "https://storage.mysoku.io/media/img3.jpg",
                ],
                "platform": [
                    {"platform": "instagram", "accountId": "ig_main"},
                    {"platform": "facebook", "accountId": "fb_page"},
                    "linkedin",
                ],
            }
        }
    })

    print(f"Post submitted: {result['postSubmissionId']}")
    return result

Generate an OG Image and Publish

Render a template image and publish it as an image post.

curl

# Step 1: Render the OG image
TEMPLATE_RESPONSE=$(curl -s -X POST https://api.mysoku.io/v1/templates \
  -H "Content-Type: application/json" \
  -H "soku-api-key: $SOKU_API_KEY" \
  -d '{
    "templateSlug": "tweetImage",
    "config": {
      "title": "5 Lessons From Building in Public",
      "author": "Soku Team",
      "theme": "dark"
    }
  }')

IMAGE_URL=$(echo "$TEMPLATE_RESPONSE" | jq -r '.url')
echo "Rendered image: $IMAGE_URL"

# Step 2: Publish the image post
curl -X POST https://api.mysoku.io/v1/posts \
  -H "Content-Type: application/json" \
  -H "soku-api-key: $SOKU_API_KEY" \
  -d "{
    \"post\": {
      \"content\": {
        \"text\": \"5 Lessons From Building in Public — a thread.\",
        \"mediaType\": \"image\",
        \"imageUrls\": [\"$IMAGE_URL\"],
        \"platform\": [\"x\", \"linkedin\"]
      }
    }
  }"

JavaScript

async function renderTemplateAndPublish() {
  // Step 1: Render the OG image
  const template = await sokuRequest('/v1/templates', {
    method: 'POST',
    body: JSON.stringify({
      templateSlug: 'tweetImage',
      config: {
        title: '5 Lessons From Building in Public',
        author: 'Soku Team',
        theme: 'dark',
      },
    }),
  });

  console.log('Rendered image:', template.url);

  // Step 2: Publish the image post
  const result = await sokuRequest('/v1/posts', {
    method: 'POST',
    body: JSON.stringify({
      post: {
        content: {
          text: '5 Lessons From Building in Public — a thread.',
          mediaType: 'image',
          imageUrls: [template.url],
          platform: ['x', 'linkedin'],
        },
      },
    }),
  });

  console.log('Post submitted:', result.postSubmissionId);
  return result;
}

Python

def render_template_and_publish():
    # Step 1: Render the OG image
    template = soku_request("/v1/templates", method="POST", json_data={
        "templateSlug": "tweetImage",
        "config": {
            "title": "5 Lessons From Building in Public",
            "author": "Soku Team",
            "theme": "dark",
        }
    })

    print(f"Rendered image: {template['url']}")

    # Step 2: Publish the image post
    result = soku_request("/v1/posts", method="POST", json_data={
        "post": {
            "content": {
                "text": "5 Lessons From Building in Public — a thread.",
                "mediaType": "image",
                "imageUrls": [template["url"]],
                "platform": ["x", "linkedin"],
            }
        }
    })

    print(f"Post submitted: {result['postSubmissionId']}")
    return result

Transcribe a Video

Submit a video for AI transcription.

curl

curl -X POST https://api.mysoku.io/v1/ai/transcribe \
  -H "Content-Type: application/json" \
  -H "soku-api-key: $SOKU_API_KEY" \
  -H "Idempotency-Key: ep42-transcribe-$(date +%Y%m%d)" \
  -d '{
    "mediaId": "media_f7e8d9c0b3c4",
    "language": "en",
    "model": "whisper-1",
    "durationSeconds": 600
  }'

JavaScript

async function transcribeVideo() {
  const transcription = await sokuRequest('/v1/ai/transcribe', {
    method: 'POST',
    headers: {
      'Idempotency-Key': `ep42-transcribe-${new Date().toISOString().slice(0, 10)}`,
    },
    body: JSON.stringify({
      mediaId: 'media_f7e8d9c0b3c4',
      language: 'en',
      model: 'whisper-1',
      durationSeconds: 600,
    }),
  });

  console.log(`Transcription job started: ${transcription.jobId}`);
  return transcription;
}

Python

from datetime import date

def transcribe_video():
    transcription = soku_request(
        "/v1/ai/transcribe",
        method="POST",
        json_data={
            "mediaId": "media_f7e8d9c0b3c4",
            "language": "en",
            "model": "whisper-1",
            "durationSeconds": 600,
        },
        extra_headers={
            "Idempotency-Key": f"ep42-transcribe-{date.today().isoformat()}"
        },
    )

    print(f"Transcription job started: {transcription['jobId']}")
    return transcription

Schedule a Post for Later

Schedule a post to be published at a specific future time.

curl

curl -X POST https://api.mysoku.io/v1/posts \
  -H "Content-Type: application/json" \
  -H "soku-api-key: $SOKU_API_KEY" \
  -d '{
    "post": {
      "content": {
        "text": "Happy Monday! Here is your weekly dose of motivation.",
        "mediaType": "text",
        "platform": ["threads", "x", "linkedin"]
      }
    },
    "scheduledTime": "2026-03-09T14:00:00.000Z"
  }'

JavaScript

async function schedulePost() {
  const result = await sokuRequest('/v1/posts', {
    method: 'POST',
    body: JSON.stringify({
      post: {
        content: {
          text: 'Happy Monday! Here is your weekly dose of motivation.',
          mediaType: 'text',
          platform: ['threads', 'x', 'linkedin'],
        },
      },
      scheduledTime: '2026-03-09T14:00:00.000Z',
    }),
  });

  console.log('Post scheduled:', result.postSubmissionId);
  return result;
}

Python

def schedule_post():
    result = soku_request("/v1/posts", method="POST", json_data={
        "post": {
            "content": {
                "text": "Happy Monday! Here is your weekly dose of motivation.",
                "mediaType": "text",
                "platform": ["threads", "x", "linkedin"],
            }
        },
        "scheduledTime": "2026-03-09T14:00:00.000Z",
    })

    print(f"Post scheduled: {result['postSubmissionId']}")
    return result

Error Handling with Retry Logic

A production-ready request function with automatic retry for transient errors.

JavaScript

const SOKU_API_KEY = process.env.SOKU_API_KEY;
const BASE_URL = 'https://api.mysoku.io';

async function sokuRequestWithRetry(path, options = {}, maxRetries = 3) {
  const url = `${BASE_URL}${path}`;
  const headers = {
    'Content-Type': 'application/json',
    'soku-api-key': SOKU_API_KEY,
    ...options.headers,
  };

  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch(url, {
      ...options,
      headers,
    });

    // Log rate limit status
    const remaining = response.headers.get('X-RateLimit-Remaining');
    const limit = response.headers.get('X-RateLimit-Limit');
    if (remaining && limit) {
      console.log(`Rate limit: ${remaining}/${limit} remaining`);
    }

    // Handle rate limiting
    if (response.status === 429) {
      if (attempt === maxRetries) {
        const body = await response.json();
        throw new Error(
          `Rate limit exceeded after ${maxRetries} retries (requestId: ${body.error?.requestId})`
        );
      }

      const retryAfter = parseInt(response.headers.get('Retry-After'), 10) || 1;
      const jitter = Math.random() * 1000;
      const delay = retryAfter * 1000 + jitter;
      console.log(`Rate limited. Waiting ${Math.round(delay / 1000)}s before retry ${attempt + 1}...`);
      await new Promise((resolve) => setTimeout(resolve, delay));
      continue;
    }

    // Handle server errors with retry
    if (response.status >= 500) {
      if (attempt === maxRetries) {
        const body = await response.json();
        throw new Error(
          `Server error after ${maxRetries} retries: ${body.error?.code} (requestId: ${body.error?.requestId})`
        );
      }

      const delay = Math.pow(2, attempt) * 1000 + Math.random() * 1000;
      console.log(`Server error. Waiting ${Math.round(delay / 1000)}s before retry ${attempt + 1}...`);
      await new Promise((resolve) => setTimeout(resolve, delay));
      continue;
    }

    // Handle client errors (no retry)
    if (!response.ok) {
      const body = await response.json();
      const error = new Error(body.error?.message || 'API request failed');
      error.code = body.error?.code;
      error.status = response.status;
      error.requestId = body.error?.requestId;
      error.details = body.error?.details;
      throw error;
    }

    // Handle 204 No Content
    if (response.status === 204) {
      return null;
    }

    return response.json();
  }
}

// Usage
async function main() {
  try {
    const result = await sokuRequestWithRetry('/v1/posts', {
      method: 'POST',
      body: JSON.stringify({
        post: {
          content: {
            text: 'Published with production-grade error handling.',
            mediaType: 'text',
            platform: ['threads'],
          },
        },
      }),
    });

    console.log('Post submitted:', result.postSubmissionId);
  } catch (error) {
    if (error.code === 'missing_integrations') {
      console.error('Connect the required platforms in Settings > Integrations.');
    } else if (error.code === 'insufficient_credits') {
      console.error('Purchase more credits at Account > Credits.');
    } else {
      console.error(`Unexpected error: ${error.message} (requestId: ${error.requestId})`);
    }
  }
}

Python

import time
import random

def soku_request_with_retry(path, method="POST", json_data=None, extra_headers=None, max_retries=3):
    url = f"{BASE_URL}{path}"
    headers = {
        "Content-Type": "application/json",
        "soku-api-key": SOKU_API_KEY,
    }
    if extra_headers:
        headers.update(extra_headers)

    for attempt in range(max_retries + 1):
        response = requests.request(method, url, json=json_data, headers=headers)

        # Log rate limit status
        remaining = response.headers.get("X-RateLimit-Remaining")
        limit = response.headers.get("X-RateLimit-Limit")
        if remaining and limit:
            print(f"Rate limit: {remaining}/{limit} remaining")

        # Handle rate limiting
        if response.status_code == 429:
            if attempt == max_retries:
                body = response.json()
                raise Exception(
                    f"Rate limit exceeded after {max_retries} retries "
                    f"(requestId: {body.get('error', {}).get('requestId')})"
                )
            retry_after = int(response.headers.get("Retry-After", 1))
            jitter = random.random()
            delay = retry_after + jitter
            print(f"Rate limited. Waiting {delay:.1f}s before retry {attempt + 1}...")
            time.sleep(delay)
            continue

        # Handle server errors with retry
        if response.status_code >= 500:
            if attempt == max_retries:
                body = response.json()
                error_info = body.get("error", {})
                raise Exception(
                    f"Server error after {max_retries} retries: {error_info.get('code')} "
                    f"(requestId: {error_info.get('requestId')})"
                )
            delay = (2 ** attempt) + random.random()
            print(f"Server error. Waiting {delay:.1f}s before retry {attempt + 1}...")
            time.sleep(delay)
            continue

        # Handle client errors (no retry)
        if not response.ok:
            body = response.json()
            error_info = body.get("error", {})
            raise Exception(
                f"API error {error_info.get('code')}: {error_info.get('message')} "
                f"(requestId: {error_info.get('requestId')})"
            )

        if response.status_code == 204:
            return None

        return response.json()

Batch Publishing Workflow

Publish multiple posts sequentially with rate limit awareness.

JavaScript

async function batchPublish(posts) {
  const results = [];

  for (const post of posts) {
    try {
      const result = await sokuRequestWithRetry('/v1/posts', {
        method: 'POST',
        body: JSON.stringify(post),
      });

      results.push({ status: 'success', postSubmissionId: result.postSubmissionId });
      console.log(`Published: ${result.postSubmissionId}`);
    } catch (error) {
      results.push({ status: 'error', code: error.code, message: error.message });
      console.error(`Failed: ${error.code} - ${error.message}`);
    }

    // Small delay between requests to avoid hitting rate limits
    await new Promise((resolve) => setTimeout(resolve, 200));
  }

  const succeeded = results.filter((r) => r.status === 'success').length;
  const failed = results.filter((r) => r.status === 'error').length;
  console.log(`Batch complete: ${succeeded} succeeded, ${failed} failed`);

  return results;
}

// Usage
const posts = [
  {
    post: {
      content: {
        text: 'Monday motivation: consistency beats perfection.',
        mediaType: 'text',
        platform: ['threads', 'x'],
      },
    },
    scheduledTime: '2026-03-09T09:00:00.000Z',
  },
  {
    post: {
      content: {
        text: 'Tuesday tip: automate what you repeat.',
        mediaType: 'text',
        platform: ['threads', 'x'],
      },
    },
    scheduledTime: '2026-03-10T09:00:00.000Z',
  },
  {
    post: {
      content: {
        text: 'Wednesday wisdom: ship it, then improve.',
        mediaType: 'text',
        platform: ['threads', 'x'],
      },
    },
    scheduledTime: '2026-03-11T09:00:00.000Z',
  },
];

batchPublish(posts);

Python

def batch_publish(posts):
    results = []

    for post in posts:
        try:
            result = soku_request_with_retry("/v1/posts", json_data=post)
            results.append({"status": "success", "postSubmissionId": result["postSubmissionId"]})
            print(f"Published: {result['postSubmissionId']}")
        except Exception as e:
            results.append({"status": "error", "message": str(e)})
            print(f"Failed: {e}")

        # Small delay between requests
        time.sleep(0.2)

    succeeded = sum(1 for r in results if r["status"] == "success")
    failed = sum(1 for r in results if r["status"] == "error")
    print(f"Batch complete: {succeeded} succeeded, {failed} failed")

    return results

API Key Rotation

Programmatically rotate an API key. This example uses Firebase ID token authentication for the key management endpoints.

curl

FIREBASE_TOKEN="eyJhbGciOiJSUzI1NiIs..."

# Step 1: Create a new key
NEW_KEY_RESPONSE=$(curl -s -X POST https://api.mysoku.io/v1/api-keys \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $FIREBASE_TOKEN" \
  -d '{"name": "Production Server (rotated)"}')

NEW_KEY=$(echo "$NEW_KEY_RESPONSE" | jq -r '.apiKey')
echo "New key created"

# Step 2: Verify the new key works
curl -s -X POST https://api.mysoku.io/v1/posts \
  -H "Content-Type: application/json" \
  -H "soku-api-key: $NEW_KEY" \
  -d '{
    "post": {
      "content": {
        "text": "Key rotation verification",
        "mediaType": "text",
        "platform": ["threads"]
      }
    }
  }'

# Step 3: Update your application environment variable
echo "Update SOKU_API_KEY to: $NEW_KEY"

# Step 4: Revoke the old key
OLD_KEY_ID="key_old_id_here"
curl -X DELETE "https://api.mysoku.io/v1/api-keys/$OLD_KEY_ID" \
  -H "Authorization: Bearer $FIREBASE_TOKEN"

echo "Old key revoked: $OLD_KEY_ID"

JavaScript

async function rotateApiKey(firebaseToken, oldKeyId) {
  const headers = {
    'Content-Type': 'application/json',
    Authorization: `Bearer ${firebaseToken}`,
  };

  // Step 1: Create a new key
  const createResponse = await fetch('https://api.mysoku.io/v1/api-keys', {
    method: 'POST',
    headers,
    body: JSON.stringify({ name: 'Production Server (rotated)' }),
  });

  const { apiKey: newApiKey } = await createResponse.json();
  console.log('New key created');

  // Step 2: Verify the new key works
  const testResponse = await fetch('https://api.mysoku.io/v1/posts', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'soku-api-key': newApiKey,
    },
    body: JSON.stringify({
      post: {
        content: {
          text: 'Key rotation verification',
          mediaType: 'text',
          platform: ['threads'],
        },
      },
    }),
  });

  if (!testResponse.ok) {
    throw new Error('New key verification failed');
  }

  console.log('New key verified successfully');

  // Step 3: Revoke the old key
  await fetch(`https://api.mysoku.io/v1/api-keys/${oldKeyId}`, {
    method: 'DELETE',
    headers: { Authorization: `Bearer ${firebaseToken}` },
  });

  console.log('Old key revoked:', oldKeyId);

  // Return the new key for your application to use
  return newApiKey;
}

Python

def rotate_api_key(firebase_token, old_key_id):
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {firebase_token}",
    }

    # Step 1: Create a new key
    create_response = requests.post(
        f"{BASE_URL}/v1/api-keys",
        headers=headers,
        json={"name": "Production Server (rotated)"},
    )
    new_api_key = create_response.json()["apiKey"]
    print("New key created")

    # Step 2: Verify the new key works
    test_response = requests.post(
        f"{BASE_URL}/v1/posts",
        headers={
            "Content-Type": "application/json",
            "soku-api-key": new_api_key,
        },
        json={
            "post": {
                "content": {
                    "text": "Key rotation verification",
                    "mediaType": "text",
                    "platform": ["threads"],
                }
            }
        },
    )

    if not test_response.ok:
        raise Exception("New key verification failed")

    print("New key verified successfully")

    # Step 3: Revoke the old key
    requests.delete(
        f"{BASE_URL}/v1/api-keys/{old_key_id}",
        headers={"Authorization": f"Bearer {firebase_token}"},
    )

    print(f"Old key revoked: {old_key_id}")
    return new_api_key

Next Steps

TopicDescription
IntroductionAPI overview and base URL
AuthenticationAPI key setup and security
Posts APIFull endpoint reference for post creation
Error HandlingComplete error code reference
Rate LimitsRate limit tiers and best practices