REST API Reference
Base URL: https://api.embeddx.org/v2. Bearer token required.
Authentication
Put a Bearer token in Authorization for every request. Create API keys in account settings.
Authorization: Bearer embx_sk_your_api_key
Keys follow your account plan. Limits by plan: Explorer 3 req/day, Engineer 100 req/day, Team 500 req/day, Enterprise custom.
POST /upload
POST /upload accepts a PDF, extracts its register model, and returns a stable Chip ID for generation.
Request
POST /v2/upload
Content-Type: multipart/form-data
file: (binary PDF)
chip_name: "STM32L476RG" // optional hint
Response 200
{
"chip_id": "embx_chip_stm32l476rg_a1b2c3",
"chip_name": "STM32L476RG",
"peripherals": ["GPIO", "USART", "SPI", "I2C", "TIM", "ADC"],
"register_count": 847,
"datasheet_pages": 1648
}
POST /generate
Generate driver output. Small datasheets under 400 pages return synchronously; larger ones return a job ID for polling.
Request body
{
"chip_id": "embx_chip_stm32l476rg_a1b2c3",
"lang": "c99", // "c99" | "cpp17" | "rust"
"peripherals": ["GPIO", "USART"], // omit for all
"include_test_stubs": false, // Engineer+ only
"webhook_url": "https://..." // optional
}
Response 200 (sync, small datasheet)
{
"status": "complete",
"chip_id": "embx_chip_stm32l476rg_a1b2c3",
"files": [
{
"filename": "stm32l476rg_gpio.h",
"content_base64": "..."
},
{
"filename": "stm32l476rg_usart.h",
"content_base64": "..."
}
],
"smoke_test": "pass",
"register_count": 191,
"accessor_count": 1342
}
Response 202 (async, large datasheet)
{
"status": "queued",
"job_id": "embx_job_x9y8z7w6",
"estimated_seconds": 45
}
GET /jobs/{id}
Check an async generation job's status.
$ curl https://api.embeddx.org/v2/jobs/embx_job_x9y8z7w6 \
-H "Authorization: Bearer embx_sk_..."
Response (complete)
{
"job_id": "embx_job_x9y8z7w6",
"status": "complete",
"files": [/* same as sync response */],
"smoke_test": "pass"
}
Possible status values
| Status | Meaning |
|---|---|
queued | Accepted, awaiting a worker |
processing | Extraction and generation in progress |
complete | Output is in files |
failed | Generation failed, see error_code |
GET /chips
List library chips and IDs. A library ID skips upload for validated chips.
{
"chips": [
{
"chip_id": "embx_lib_stm32l476rg",
"chip_name": "STM32L476RG",
"vendor": "STMicroelectronics",
"peripherals": ["GPIO", "USART", "SPI", "I2C", "TIM", "ADC", "DMA"]
}
/* ... */
],
"total": 183
}
Webhook callbacks
Add webhook_url to the generation request to POST a completion callback. Its payload matches GET /jobs/{id}.
The X-Embedd-Signature header carries an HMAC-SHA256 signature of the raw body, made with your account's webhook secret. Verify it before processing.
Signature verification (Python)
import hmac, hashlib
def verify_webhook(secret, payload_bytes, signature_header):
expected = hmac.new(
secret.encode(),
payload_bytes,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature_header)
On HTTP 4xx/5xx, deliveries retry with exponential backoff up to 3 times. Return HTTP 200 to acknowledge.
Error codes
| HTTP | Code | Meaning |
|---|---|---|
| 401 | INVALID_KEY | API key missing or invalid |
| 403 | PLAN_LIMIT | Request exceeds plan quota |
| 404 | CHIP_NOT_FOUND | Chip ID does not exist |
| 413 | FILE_TOO_LARGE | PDF exceeds 200 MB limit |
| 422 | EXTRACTION_FAILED | Register model extraction from the PDF failed |
| 422 | UNSUPPORTED_LANG | Language unavailable on plan |
| 429 | RATE_LIMITED | Too many requests. Retry using Retry-After. |
| 500 | INTERNAL_ERROR | Server error; the request ID is in X-Request-ID. |
Every error response has a JSON body containing error_code and message.