How to call REST APIs from Macro Scheduler (with JSON, headers, error handling)

Published on October 6, 2025 by Marcus Tettmar in Uncategorized

TL;DR: Use HTTPRequest for GET/POST/PUT/PATCH/DELETE, set HTTP_POSTJSON=1 for JSON bodies, add HTTP_CUSTOM_HEADERS for auth, HTTP_TIMEOUT for reliability, and parse responses with JSONParse.

Why call APIs from Macro Scheduler?

  • Pull or push data (orders, tickets, metrics) as part of a daily job
  • Trigger SaaS workflows without opening a browser
  • Glue apps together (cron-style) with simple, reliable scripts

Everything below runs in plain Macro Scheduler—no external dependencies.


Quick start: GET a JSON endpoint

// 1) Optional: set a timeout (seconds)
Let>HTTP_TIMEOUT=15

// 2) Optional: custom headers (multiple lines use %CRLF%)
Let>HTTP_CUSTOM_HEADERS=Accept: application/json

// 3) Make the request
HTTPRequest>https://api.example.com/status,,GET,,RESP

// 4) Parse JSON (example path)
JSONParse>RESP,$.service,result
If>result_count>0
  MessageModal>Service: %result_1%
Else
  // Log full response if JSON path not found
  WriteLn>%SCRIPT_DIR%\api_log.txt,WF_APPEND,Unexpected response: %RESP%
EndIf

HTTPRequest signature:
HTTPRequest>URL,[LocalFilename],Method,[POST_Data],Result_Variable mjtnet.com

POST JSON (with Bearer token)

Let>HTTP_TIMEOUT=20
Let>HTTP_POSTJSON=1
Let>HTTP_CUSTOM_HEADERS=Authorization: Bearer YOUR_API_KEY%CRLF%Accept: application/json

// JSON body (can be built up dynamically)
Let>payload={"name":"Widget 42","price":19.99}

// POST it
HTTPRequest>https://api.example.com/items,,POST,payload,RESP

// Extract a field from the JSON response
JSONParse>RESP,$.id,itemId
If>itemId_count=1
  MessageModal>Created item id: %itemId_1%
Else
  WriteLn>%SCRIPT_DIR%\api_log.txt,WF_APPEND,Create failed: %RESP%
EndIf
  • For JSON bodies, set HTTP_POSTJSON=1 (Macro Scheduler sets the content type for you). mjtnet.com
  • JSONParse returns an array (result_1result_2, …) with a *_count—use JSONPath like $.idmjtnet.com

Custom headers, SSL/TLS & timeouts (reliability)

Let>HTTP_TIMEOUT=30
Let>HTTP_CUSTOM_HEADERS=Authorization: Bearer YOUR_API_KEY%CRLF%X-Trace: msched
  • Timeouts: set HTTP_TIMEOUT (seconds) so a hung API doesn’t block your run. mjtnet.com
  • Headers: set multiple lines via HTTP_CUSTOM_HEADERS—great for auth, idempotency keys, etc. mjtnet.com
  • HTTPS/TLS: Use an https:// URL (or set HTTP_SSL=1). If you must pin a TLS version, set TLS_VER (12 for TLS 1.2). 

Example: create a short link with a custom Open Graph preview (ogli)

Swap in your endpoint/headers if you’re using another service—the pattern is the same.

This example uses the Ogli link shorter service. Grab a free API key from Ogli to try out the code below.

// Go get a free API key from app.ogli.sh
Let>OGLI_API_KEY=YOUR_API_KEY_HERE

// Timeouts & JSON
Let>HTTP_TIMEOUT=20
Let>HTTP_POSTJSON=1

// Auth (Bearer) + accept JSON
Let>HTTP_CUSTOM_HEADERS=Authorization: Bearer %OGLI_API_KEY%%CRLF%Accept: application/json

// Build the request body
/*
PAYLOAD:
{
"targetUrl":"https://example.com/product/1232",
"title":"SuperWidget — Launch Day"
}
*/
LabelToVar>PAYLOAD,postBody

// POST
HTTPRequest>https://api.ogli.sh/link,,POST,postBody,RESP

// Parse shortUrl from response
JSONParse>RESP,$.url,short_link
If>short_link_count>0
  Let>the_link=short_link_1
  MessageModal>short link is %the_link%
Endif

Later, PATCH the same link to swap the OG image and platforms will refresh the preview when reshared.

Error handling & logging pattern

Let>LOG=%SCRIPT_DIR%\api_log.txt

// After any HTTPRequest:
If>RESP=
  // If you saved to a LocalFileName, RESP will be blank on success.
  // Otherwise blank usually means an error occurred – log it:
  WriteLn>%LOG%,WF_APPEND,Blank response (check URL/timeout/SSL)
Else
  // Try to parse a known field; if none, log full response
  JSONParse>RESP,$.status,status
  If>status_count=0
    WriteLn>%LOG%,WF_APPEND,Unexpected JSON: %RESP%
  EndIf
EndIf

Tip: when you save to a file (use the LocalFilename parameter), a successful call leaves the result variable blank by design; otherwise it contains the response or an error message. mjtnet.com


Parse more JSON with JSONPath

/*
RESP:
{
  "id":"lnk_abc123",
  "shortUrl":"https://ogli.sh/launch-123",
  "stats":{"clicks":42,"countries":["GB","US"]}
}
*/
JSONParse>RESP,$.stats.clicks,c
If>c_count=1
  Let>clicks=%c_1%
EndIf

// Loop an array (countries)
JSONParse>RESP,$.stats.countries[*],cc
Let>k=0
Repeat>k
  Let>k=k+1
  Let>country=cc_%k%
  // do something with %country%
Until>k=cc_count

JSONParse returns an array and a *_count—loop over it with Repeat/Until

Common gotchas

  • For JSON, always set HTTP_POSTJSON=1 (don’t hand-craft Content-Type). mjtnet.com
  • Escape quotes inside JSON strings correctly.
  • Use timeouts so a bad endpoint doesn’t hang your run (Let>HTTP_TIMEOUT=15). mjtnet.com
  • If an API returns HTML (error pages), JSONParse will fail—log RESP to inspect.

Further reading

  • Macro Scheduler: HTTPRequest (methods, headers, files, SSL, timeouts). mjtnet.com
  • Macro Scheduler: JSONParse (JSONPath, arrays, examples). 
  • If you prefer you can use Python requests with PyExec.