Custom Application Integration
This guide uses Chat Completions. Have a valid API Key and a complete model ID that supports this API ready.
1. Save the request body
Create request.json in your current working directory. Save the following as UTF-8 without a BOM, replacing YOUR_MODEL_ID with a real model ID:
{
"model": "YOUR_MODEL_ID",
"messages": [
{"role": "user", "content": "Introduce yourself in one sentence."}
],
"stream": false
}The file contains no API Key and can be reused for tests. Do not send the placeholder model value unchanged.
2. Run the request for your operating system
On macOS / Linux, open a terminal in the directory containing request.json:
export CERTAEDGE_API_KEY='sk-YOUR_API_KEY'
curl -i -sS https://certaedge.com/v1/chat/completions \
-H "Authorization: Bearer $CERTAEDGE_API_KEY" \
-H 'Content-Type: application/json' \
--data-binary @request.jsonIn Windows PowerShell, use curl.exe so older PowerShell versions do not interpret curl as another command:
$env:CERTAEDGE_API_KEY = 'sk-YOUR_API_KEY'
curl.exe -i -sS https://certaedge.com/v1/chat/completions -H "Authorization: Bearer $env:CERTAEDGE_API_KEY" -H "Content-Type: application/json" --data-binary "@request.json"Replace sk-YOUR_API_KEY with your complete key. The command already contains the full endpoint; do not append /v1 or /chat/completions again.
3. Confirm success
-i displays HTTP response headers. On success, the final response status is 200, choices[0].message.content in the JSON contains a reply, and a matching record appears in Usage Logs. Model calls are billed for actual usage.
Troubleshoot by status code only after receiving an HTTP response. For DNS, TLS, or connection timeout errors, first check the address and network.
Common issues
| Symptom | What to do |
|---|---|
request.json not found | Run the command in the file's directory and check it was not saved as .json.txt |
| 400 / JSON parsing failure | Check commas, quotes, file encoding, and the model placeholder |
| 401 | Check the complete key in the current terminal, its expiration, and enabled status |
| 404 | Check the endpoint and model ID, and confirm Chat Completions support |
| 429 | Read the error body, then check request frequency, balance, and key quota |
Responses, Anthropic Messages, and other APIs require their own request structures. Changing the URL alone is not enough. In a production application, store keys in server-side environment variables or protected credential storage.
Query generation tasks with Python
The following script only queries an already submitted video task and downloads its result. It never submits or regenerates a task. Obtain a real id using the video API guide, then set your key and task ID.
macOS / Linux:
export CERTAEDGE_API_KEY='sk-YOUR_API_KEY'
export CERTAEDGE_TASK_ID='task_EXAMPLE'Windows PowerShell:
$env:CERTAEDGE_API_KEY = 'sk-YOUR_API_KEY'
$env:CERTAEDGE_TASK_ID = 'task_EXAMPLE'Save the following as poll_video.py. It uses only the Python standard library, with no additional SDK required. Run it in a separate test directory.
import json
import os
import shutil
import time
import urllib.parse
import urllib.request
from pathlib import Path
class NoRedirect(urllib.request.HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
api_key = os.environ["CERTAEDGE_API_KEY"]
task_id = os.environ["CERTAEDGE_TASK_ID"]
if not task_id.startswith("task_"):
raise ValueError("Use the real task ID from the video submission response")
base = "https://certaedge.com"
headers = {"Authorization": f"Bearer {api_key}"}
encoded_id = urllib.parse.quote(task_id, safe="")
status_url = f"{base}/v1/videos/{encoded_id}"
opener = urllib.request.build_opener(NoRedirect())
for attempt in range(60):
request = urllib.request.Request(status_url, headers=headers)
with opener.open(request, timeout=60) as response:
task = json.load(response)
status = task.get("status")
print(f"Query {attempt + 1}: {status}")
if status == "completed":
break
if status == "failed":
raise RuntimeError(task.get("error") or "Generation failed")
if status not in {"queued", "in_progress"}:
raise RuntimeError(f"Unknown status: {status}")
if attempt < 59:
time.sleep(15)
else:
raise TimeoutError("Waiting ended; keep the task ID to query later and do not resubmit automatically")
output = Path("result.mp4")
if output.exists():
raise FileExistsError("result.mp4 already exists; rename or move the old file first")
request = urllib.request.Request(f"{status_url}/content", headers=headers)
with opener.open(request, timeout=120) as response:
content_type = response.headers.get_content_type()
if not (content_type.startswith("video/") or content_type == "application/octet-stream"):
raise RuntimeError(f"Response is not video: {content_type}")
with output.open("xb") as target:
shutil.copyfileobj(response, target)
print(f"Saved to {output.resolve()}")Run python3 poll_video.py on macOS / Linux or py -3 poll_video.py on Windows. If you already have a virtual environment, you can also use the Python path from the first-request guide.
The script queries at most 60 times, roughly 15 seconds apart. Completion within that time is not guaranteed. Network or HTTP errors, unknown statuses, and redirects stop the script so you can check the address and continue querying the same task. It does not automatically forward the authorization header to another host.
The script stops if the task fails. An interrupted download may leave a partial local file; inspect and move it before downloading again. Existing result.mp4 files are never overwritten.
Extend this into a business workflow
- Batch generation: save the task ID, business record, and query count separately for every submission. Limit concurrency and do not share a single ID variable.
- Multiple artifacts: use the generic artifact list and save audio, images, or video according to their actual
typeandkey. - Background Responses: query with the returned response ID. Do not insert
resp_...into this script's video path. - Database writes or notifications: act only after confirming a terminal state, and deduplicate by task ID so every query does not send the same notification again.