Propagate runtime ID across API requests
StripeSoftware Engineer · Technical ScreenLast updated
Implement a request interpolator that traverses nested request payloads and URLs to replace placeholder variables with runtime IDs while preserving native data types.
Propagate Runtime ID Across API Requests
When orchestrating end-to-end integration workflows, an API runner often executes a sequence of requests where downstream calls depend on IDs or values generated by earlier responses.
You are tasked with implementing a function interpolate_request that resolves template placeholders in an HTTP request template using values from a runtime context dictionary.
Requirements
-
Placeholder Syntax:
- Placeholders are formatted as
{{path.to.key}}. - Keys are alphanumeric and may contain dots (
.) to represent nested lookup incontext(e.g.,{{customer.default_source}}maps tocontext["customer"]["default_source"]).
- Placeholders are formatted as
-
Type-Preserving Replacement:
- If a string field matches exactly a single placeholder (e.g.,
"{{payment.amount}}"), it must be replaced with the actual runtime value and its original type (e.g., integer5000, booleantrue, or a nested object/list). - If a placeholder is embedded within surrounding text (e.g.,
"/v1/customers/{{customer.id}}/cards"), interpolate the string representation of the resolved value.
- If a string field matches exactly a single placeholder (e.g.,
-
Nested Data Traversal:
- The request
bodycan contain arbitrary JSON structures: dictionaries, lists, strings, numbers, booleans, and nulls. - You must recursively traverse and interpolate all placeholders within
url,headers, andbody.
- The request
-
Missing Keys:
- If any placeholder path does not exist in
context, raise aKeyError.
- If any placeholder path does not exist in
Function Signature
def interpolate_request(request: dict, context: dict) -> dict:
pass
Input and Output Format
request: A dictionary containing at least"url"(str), and optionally"headers"(dict[str, str]) and"body"(JSON-compatible data: dict, list, primitive, or None).context: A nested dictionary containing runtime values produced by previous requests.- Returns a new dictionary with the exact same structure as
request, where all placeholders have been replaced.
Example 1
request = {
"url": "/v1/charges/{{charge.id}}/refund",
"headers": {"Idempotency-Key": "refund-{{charge.id}}"},
"body": {
"amount": "{{charge.amount}}",
"metadata": {
"customer": "{{charge.customer.id}}",
"full_refund": "{{charge.metadata.is_full}}"
}
}
}
context = {
"charge": {
"id": "ch_12345",
"amount": 2500,
"customer": {"id": "cus_9999"},
"metadata": {"is_full": True}
}
}
# Output:
{
"url": "/v1/charges/ch_12345/refund",
"headers": {"Idempotency-Key": "refund-ch_12345"},
"body": {
"amount": 2500, # Preserved as int, not "2500"
"metadata": {
"customer": "cus_9999",
"full_refund": True # Preserved as bool
}
}
}
Constraints
requestJSON depth<= 10.- Context keys are valid identifier strings matching
[a-zA-Z0-9_]+. - String values may contain zero, one, or multiple placeholders.
Hints
Hint 1
Differentiate between strings that consist solely of a single placeholder `^\{\{([^}]+)\}\}$` and strings that have surrounding characters or multiple placeholders.
Hint 2
Write a helper function to resolve dot-separated paths (e.g. `"a.b.c"`) by recursively or iteratively traversing the context dictionary.
Hint 3
Recursively traverse the request structure: handle dictionaries, lists, and primitives (strings vs non-strings) as distinct cases.
Follow-up questions
- How would you handle cyclic references in the context dictionary or circular dependencies across chained requests?
- If placeholder replacement supported default values (e.g., `{{customer.name | 'Anonymous'}}`), how would you update your parser?
- How would you optimize memory usage and performance if request bodies are large (e.g., megabytes of batch data)?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.