Integrate
Using DocxAPI in n8n
The most common setup: build content in your workflow, convert it to Word, then store or send the file. One HTTP Request node does the conversion.
Reading this with an AI agent?
The entire documentation lives in one Markdown file, built to be fetched and read by an LLM. Copy the prompt below and paste it into ChatGPT, Claude, Cursor or any agent with web access — it asks the agent to read the file before helping you.
HTTP Request node
Add an HTTP Request node and configure it exactly like this:
| Field | Value |
|---|---|
| Method | POST |
| URL | https://api.searchops.io/v1/generate |
| Send Headers | on → name x-api-key, value your key |
| Send Body | on → Body Parameters |
Body · input | markdown, html or json |
Body · content | your expression, e.g. ={{ $json.body }} |
Body · format | file |
| Options → Response → Response Format | File |
This is the setting people miss. There are two different “file” settings and you need both: format: "file" in the body tells the API to return binary, and Options → Response → Response Format → File tells n8n to treat the reply as binary. Set only one and you get a corrupted or empty document.
In n8n's Body Parameters UI the short aliases input and format are the natural fields to type — they are equivalent to input_type and response_format.
Importable workflow
Copy this and use Import from clipboard in n8n. It converts Markdown and uploads the result to Google Drive. Replace the API key, the drive ID and the folder.
{
"nodes": [
{
"parameters": {
"method": "POST",
"url": "https://api.searchops.io/v1/generate",
"sendHeaders": true,
"headerParameters": {
"parameters": [{ "name": "x-api-key", "value": "sk_live_YOUR_KEY" }]
},
"sendBody": true,
"bodyParameters": {
"parameters": [
{ "name": "input", "value": "markdown" },
{ "name": "content", "value": "=# {{ $json.title }}\n\n{{ $json.body }}" },
{ "name": "format", "value": "file" }
]
},
"options": { "response": { "response": { "responseFormat": "file" } } }
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.4,
"position": [2064, 1744],
"id": "2c162942-2d5f-408d-aa5d-b1847c4abb61",
"name": "MD to Docx"
},
{
"parameters": {
"name": "=Title",
"driveId": { "__rl": true, "value": "=id-drive", "mode": "id" },
"folderId": { "__rl": true, "value": "=url-folder", "mode": "url" },
"options": {}
},
"type": "n8n-nodes-base.googleDrive",
"typeVersion": 3,
"position": [2272, 1744],
"id": "75e1a243-6c4a-4647-83b4-af50c7f0922c",
"name": "Upload to Drive",
"onError": "continueErrorOutput"
}
],
"connections": {
"MD to Docx": { "main": [[{ "node": "Upload to Drive", "type": "main", "index": 0 }]] }
},
"pinData": {}
}The Google Drive node picks up the binary from the previous node automatically — there is nothing to map.
Feeding it from an AI node
A frequent pattern is an LLM node producing Markdown that becomes the document. Wire the model output straight into content:
=# {{ $json.title }}
{{ $json.output }}Markdown is the best input for this: language models already write it, and headings, lists and tables carry over into Word without extra work.
Naming the uploaded file
Two options, and they are independent:
- Send
filenamein the body — the API sets theContent-Disposition, which most nodes respect. - Set the Name field on the Google Drive node — this wins for the stored file.
Setting the name at the destination node is the more predictable of the two.
Handling failures
Set onError: continueErrorOutput on the node (as in the workflow above) so a failed conversion routes to a separate branch instead of stopping the run.
Worth retrying: 429 (rate limit), 503 (queue full) and 504 (timeout). Everything else in the 4xx range needs a change to the request, not a retry. The full list is in the API reference.