CodeWords API key
The CodeWords API lets any external application trigger your workflows with simple HTTP requests. Whether you're building a web app, mobile app, or connecting to third-party services, it's as easy as making a POST request.
Getting your API key
First things first — you'll need credentials. Grab your API key from the Codewords account dashboard.
Your API key will be under the Your API keys section:
cwk-
for standard reusable keys (most common)cwotk-
for one-time keys (extra security for sensitive operations)
Pro tip: Treat your API key like a password — keep it secret and store it as an environment variable.
How the API works
Base URL: https://runtime.codewords.ai
The endpoints you'll use:
Quick tasks:
POST /run/{serviceId}
(under two minutes)Heavy lifting:
POST /run_async/{serviceId}
(up to 30 minutes)Check results:
GET /result/{request_id}
(for async calls)Watch progress:
GET /logs/{request_id}
(live streaming)Upload files:
POST /file
(when your workflow needs files)
Authentication: Just add Authorization: Bearer {YOUR_API_KEY}
to your headers.
Quick synchronous calls
Perfect for automations that finish fast (under two minutes). Your request waits for the result and gets it back immediately.
Using cURL
# Basic call to a LinkedIn enricher
curl -X POST https://runtime.codewords.ai/run/linkedin-enricher \
-H "Authorization: Bearer cwk-your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"spreadsheet": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
"include_email": false,
"output_columns": ["bio", "location", "current_job"]
}'
# Success response:
# {
# "status": "completed",
# "processed_count": 25,
# "success_rate": 0.92,
# "updated_sheet_url": "https://docs.google.com/spreadsheets/d/...",
# "summary": "## Enrichment Complete\n\n✅ **25 profiles processed**..."
# }
# If it takes too long:
# HTTP 504 Gateway Timeout (switch to async!)
Python example
Install the CodeWords client first:
pip install codewords-client
import os
from codewords_client import AsyncCodewordsClient
import asyncio
# Set your API key as environment variable
# export CODEWORDS_API_KEY=cwk-your-api-key-here
async def enrich_linkedin_profiles(spreadsheet_id: str):
"""Call the LinkedIn enricher and get results back immediately."""
async with AsyncCodewordsClient() as client:
try:
response = await client.run(
service_id="linkedin-enricher",
inputs={
"spreadsheet": spreadsheet_id,
"include_email": False,
"output_columns": ["bio", "location", "current_job"]
}
)
response.raise_for_status()
return response.json()
except Exception as e:
if "504" in str(e) or "timeout" in str(e).lower():
raise TimeoutError("Service took too long - try async instead")
raise
# Usage
async def main():
try:
result = await enrich_linkedin_profiles("1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms")
print(f"Processed {result['processed_count']} profiles")
print(f"Success rate: {result['success_rate']:.1%}")
except TimeoutError:
print("That took too long - consider using async execution")
asyncio.run(main())
JavaScript/TypeScript example
Install the client:
npm install @codewords/client
import { createServiceClient } from "@codewords/client";
// Set your API key as environment variable
const client = createServiceClient(process.env.CODEWORDS_API_KEY!);
interface LinkedInRequest {
spreadsheet: string;
include_email: boolean;
output_columns: string[];
}
async function enrichLinkedInProfiles(request: LinkedInRequest) {
try {
const result = await client.runService(
"linkedin-enricher", // service ID
"", // path (empty for main endpoint)
request // your data
);
return result;
} catch (error) {
if (error.response?.status === 504) {
throw new Error("Service timed out - try async execution");
}
throw error;
}
}
// Usage
const request = {
spreadsheet: "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
include_email: false,
output_columns: ["bio", "location", "current_job"]
};
const result = await enrichLinkedInProfiles(request);
console.log(`Processed ${result.processed_count} profiles`);
Asynchronous calls for heavy lifting
For automations that need more time (up to 30 minutes), use async execution. You'll get a request ID immediately, then check back for results.
Using cURL
# 1. Start the async job
curl -X POST https://runtime.codewords.ai/run_async/linkedin-enricher \
-H "Authorization: Bearer cwk-your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"spreadsheet": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
"include_email": true,
"output_columns": ["bio", "location", "current_job", "education"]
}'
# Response: {"request_id": "req_abc123def456"}
# 2. Check if it's done (might return 408 if still running)
curl -X GET "https://runtime.codewords.ai/result/req_abc123def456" \
-H "Authorization: Bearer cwk-your-api-key-here"
# Not ready: HTTP 408 Request Timeout
# Ready: Full result with status 200
# 3. Optional: Watch live logs
curl -X GET "https://runtime.codewords.ai/logs/req_abc123def456" \
-H "Authorization: Bearer cwk-your-api-key-here" \
-H "Accept: text/event-stream"
Python example
from codewords_client import AsyncCodewordsClient
import asyncio
async def enrich_profiles_async(spreadsheet_id: str):
"""Start a big job and wait for it to finish."""
async with AsyncCodewordsClient() as client:
# Start the job in background
handle = await client.run(
service_id="linkedin-enricher",
inputs={
"spreadsheet": spreadsheet_id,
"include_email": True,
"output_columns": ["bio", "location", "current_job", "education"]
},
in_background=True # This makes it async
)
print(f"Started background job: {handle.request_id}")
# Wait for it to finish (up to 10 minutes)
response = await handle.result(timeout_seconds=600)
return response.json()
# Usage
async def main():
result = await enrich_profiles_async("1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms")
print(f"Async job completed!")
print(f"Processed {result['processed_count']} profiles")
asyncio.run(main())
TypeScript example
import { createServiceClient } from "@codewords/client";
const client = createServiceClient(process.env.CODEWORDS_API_KEY!);
async function enrichProfilesAsync(request: LinkedInRequest) {
// Start async execution
const requestId = await client.runAsync(
"linkedin-enricher",
"",
request
);
console.log(`Started async job: ${requestId}`);
// Wait for results (10 minutes max)
const result = await client.pollResult(600000);
if (result.responseStatus === 200) {
return result.responseJson;
} else {
throw new Error(`Job failed with status ${result.responseStatus}`);
}
}
Working with files
When your CodeWords automation needs file inputs, upload them first and pass the download URLs.
Upload and process pattern
from codewords_client import AsyncCodewordsClient
async def process_my_csv(file_path: str):
"""Upload a local file and process it with CodeWords."""
async with AsyncCodewordsClient() as client:
# Read your local file
with open(file_path, 'rb') as f:
file_content = f.read()
# Upload to CodeWords
download_url = await client.upload_file_content(
filename="data.csv",
file_content=file_content
)
# Process with your automation
response = await client.run(
service_id="csv-processor",
inputs={
"csv_file": download_url,
"processing_options": {"header_row": True}
}
)
return response.json()
# Usage
result = await process_my_csv("./my-data.csv")
print(f"Processed {result['row_count']} rows")
Integrating with web apps
Here's how to add CodeWords to a Flask web application:
from flask import Flask, request, jsonify
from codewords_client import AsyncCodewordsClient
import asyncio
app = Flask(__name__)
@app.route('/analyze-spreadsheet', methods=['POST'])
def analyze_spreadsheet():
"""API endpoint that calls CodeWords behind the scenes."""
data = request.get_json()
spreadsheet_id = data.get('spreadsheet_id')
if not spreadsheet_id:
return jsonify({"error": "spreadsheet_id required"}), 400
async def call_codewords():
async with AsyncCodewordsClient() as client:
response = await client.run(
service_id="linkedin-enricher",
inputs={
"spreadsheet": spreadsheet_id,
"include_email": False,
"output_columns": ["bio", "location", "current_job"]
}
)
return response.json()
try:
result = asyncio.run(call_codewords())
return jsonify(result)
except Exception as e:
if "timeout" in str(e).lower():
return jsonify({"error": "Analysis timed out"}), 408
return jsonify({"error": str(e)}), 500
if __name__ == '__main__':
app.run(debug=True)
Error handling best practices
Make your API calls bulletproof with smart retry logic:
from codewords_client import AsyncCodewordsClient
import asyncio
import logging
async def bulletproof_call(
service_id: str,
inputs: dict,
max_retries: int = 3
):
"""Make a robust call with automatic retry and timeout handling."""
async with AsyncCodewordsClient() as client:
for attempt in range(max_retries):
try:
# Try sync first
response = await client.run(
service_id=service_id,
inputs=inputs
)
return response.json()
except Exception as e:
if "timeout" in str(e).lower() or "504" in str(e):
# Switch to async for timeouts
logging.info("Switching to async mode due to timeout...")
handle = await client.run(
service_id=service_id,
inputs=inputs,
in_background=True
)
response = await handle.result(timeout_seconds=600)
return response.json()
# Retry on other errors
if attempt < max_retries - 1:
await asyncio.sleep(2 ** attempt) # Exponential backoff
continue
raise
# Usage
try:
result = await bulletproof_call("my-automation", {"input": "data"})
print("Success!")
except Exception as e:
print(f"Failed after retries: {e}")
Last updated