ctify
Documentation
API key & onboarding

FastAPI

Use this when your service is a vanilla FastAPI stack. Call the Actify API in parallel with your own work, then merge _commerce_layer when the response includes it.

Install

pip install httpx==0.27.* fastapi==0.115.* uvicorn==0.30.*

Actify API client (actify_client.py)

Drop this module into your project — it is the only new helper you need.

# actify_client.py
import os
from typing import Any
import httpx

ACTIFY_BASE_URL = os.environ.get("ACTIFY_BASE_URL", "https://actify-api.vercel.app")
ACTIFY_API_KEY  = os.environ["ACTIFY_API_KEY"]
ACTIFY_TIMEOUT  = float(os.environ.get("ACTIFY_TIMEOUT_S", "1.5"))

_client = httpx.AsyncClient(
    base_url=ACTIFY_BASE_URL,
    headers={"Authorization": f"Bearer {ACTIFY_API_KEY}"},
    timeout=httpx.Timeout(ACTIFY_TIMEOUT),
)

async def fetch_actify_match(task_query: str, **context: Any) -> dict | None:
    """Returns the _commerce_layer block, or None on no-intent / error."""
    payload: dict[str, Any] = {"task_query": task_query}
    if context:
        payload["context_metadata"] = context
    try:
        resp = await _client.post("/v1/match", json=payload)
        if resp.status_code != 200:
            return None
        return (resp.json() or {}).get("_commerce_layer")
    except Exception:
        return None

Wire into a handler

# main.py
import asyncio
from fastapi import FastAPI
from pydantic import BaseModel
from actify_client import fetch_actify_match

app = FastAPI()

class QueryRequest(BaseModel):
    query: str

@app.post("/answer")
async def answer(req: QueryRequest):
    ad_task = asyncio.create_task(
        fetch_actify_match(req.query, service_name="my_service")
    )

    result = await your_existing_logic(req.query)

    commerce = await ad_task
    if commerce:
        result["_commerce_layer"] = commerce

    return result

Rules

  • Run the Actify API call in parallel — never block your handler on it first.
  • Set `ACTIFY_TIMEOUT_S` to match when you send the response — ~1–2 s is a common starting point; shorter caps drop `_commerce_layer` more often on fast paths or cold starts.
  • Send only the user’s raw query in task_query — not your draft answer.
  • Forward recommendation URLs verbatim to your assistant layer.
  • If fetch_actify_match returns None, return your response without a commerce block.