JSON collection and Python parameters
ctx.http() returns a Response. Check its status, parse JSON, then verify the expected structure. An HTML error page must not silently become an empty catalog.
def run(ctx):
url = ctx.param('api_url', '')
if not url:
ctx.abort('Enter the data URL')
response = ctx.http().with_headers({'Accept': 'application/json'}).get(url)
if not response.ok():
ctx.fail('Source returned HTTP ' + str(response.status))
payload = response.json()
if not isinstance(payload, dict) or not isinstance(payload.get('items'), list):
ctx.fail('Expected an object with an items list')
for item in payload['items']:
if not isinstance(item, dict):
ctx.fail('Each items element must be an object')
sku = str(item.get('sku') or '')
if not sku:
continue
ctx.emit({
'sku': sku,
'name': str(item.get('name') or ''),
'price': ctx.text().money(item.get('price')),
}, sku)
dict.get() returns the same default for a missing key and a key explicitly set to None. Use 'price' in item when the distinction matters. Do not replace a valid zero price with a fallback through or. Use money() for prices containing separators or currency symbols.
ctx.json(text) parses an existing JSON string locally. The permitted json module can serialize POST data with json.dumps(). Set Content-Type: application/json through with_headers and pass a serialized string as the request body; a Python dictionary does not imply a JSON HTTP body.
Secrets
Read a configured site secret with ctx.credential('site_token'). Do not place it in code, query strings, logs, or emitted records. A site credential and an export token serve different purposes; configure export token scopes independently.