{"openapi":"3.1.0","info":{"title":"Knobase Ads API","version":"1.0.0","description":"UI-neutral sponsored-offer decision and tracked-link service. Knobase does not modify the publisher organic AI answer and never requires a card, panel, empty slot, or new chat UI. No-fill is a successful result."},"servers":[{"url":"https://knobase.com"}],"tags":[{"name":"Decide"},{"name":"Affiliate"},{"name":"Redirect"},{"name":"Events"},{"name":"Decisions"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API key","description":"Server-side KNOBASE_API_KEY. Setup tokens (kb_setup_) are rejected."}},"schemas":{"ContextEnvelope":{"type":"object","additionalProperties":false,"properties":{"message":{"type":"string","maxLength":4000,"description":"Current user turn only. Transient. Not persisted."},"session":{"type":"object","additionalProperties":false,"properties":{"token":{"type":"string","maxLength":128},"digest":{"$ref":"#/components/schemas/SessionDigest"}}},"locale":{"type":"string","minLength":2,"maxLength":16},"country":{"type":"string","minLength":2,"maxLength":8},"audience":{"$ref":"#/components/schemas/Audience"},"native_surface":{"$ref":"#/components/schemas/NativeSurface"}},"required":["native_surface"]},"NativeSurface":{"type":"object","additionalProperties":false,"required":["clickable","disclosure_capable"],"properties":{"clickable":{"type":"boolean","description":"Existing separate clickable surface. Self-attestation only."},"disclosure_capable":{"type":"boolean","description":"Can show sponsorship disclosure and advertiser identity. Self-attestation only."}}},"SessionDigest":{"type":"object","additionalProperties":false,"properties":{"intent_type":{"type":"string","enum":["purchase","compare","browse","low","unknown"]},"category_ids":{"type":"array","maxItems":20,"items":{"type":"string","maxLength":64}},"entity_ids":{"type":"array","maxItems":20,"items":{"type":"string","maxLength":64}},"excluded_entity_ids":{"type":"array","maxItems":20,"items":{"type":"string","maxLength":64}},"budget_bucket":{"type":"string","enum":["unknown","low","mid","high"]},"safety":{"type":"string","enum":["clear","unknown","blocked"]},"generated_at":{"type":"string","maxLength":40}}},"Audience":{"type":"object","additionalProperties":false,"properties":{"age_band":{"type":"string","enum":["under_13","13_17","18_plus","unknown"]},"contextual_offer_consent":{"type":"boolean"}}},"DecideServe":{"type":"object","required":["serve","request_id","decision_id","offer_id","expires_at","disclosure","advertiser","link","reason_codes"],"properties":{"serve":{"type":"boolean","const":true},"request_id":{"type":"string"},"decision_id":{"type":"string"},"offer_id":{"type":"string","description":"Snapshot id (snp_…). Use as offer_snapshot_id on events."},"expires_at":{"type":["string","null"]},"disclosure":{"type":"string"},"advertiser":{"type":"string"},"link":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"image_url":{"type":"string"},"cta":{"type":"string"},"reason_codes":{"type":"array","items":{"type":"string"}}}},"DecideNoFill":{"type":"object","required":["serve","request_id","decision_id","reason_codes"],"properties":{"serve":{"type":"boolean","const":false},"request_id":{"type":"string"},"decision_id":{"type":"string"},"reason_codes":{"type":"array","items":{"type":"string"}},"retry_after_seconds":{"type":"number"}}},"AuthError":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"error":{"type":"string"},"reason_codes":{"type":"array","items":{"type":"string"}}}},"ImpressionEvent":{"type":"object","required":["offer_snapshot_id"],"properties":{"offer_snapshot_id":{"type":"string","pattern":"^snp_"},"decision_id":{"type":"string","pattern":"^dec_"},"type":{"type":"string","enum":["offer_rendered","qualified_impression"]},"idempotency_key":{"type":"string","minLength":8,"maxLength":80}}},"ConversionEvent":{"type":"object","required":["offer_snapshot_id","timestamp","nonce","signature"],"properties":{"offer_snapshot_id":{"type":"string","pattern":"^snp_"},"decision_id":{"type":"string","pattern":"^dec_"},"timestamp":{"type":"integer"},"nonce":{"type":"string","minLength":8,"maxLength":80},"signature":{"type":"string","minLength":16}}}}},"paths":{"/v1/offers/decide":{"post":{"tags":["Decide"],"summary":"Decide whether to return a labeled tracked offer","description":"Server-side only. Do not rewrite the organic answer. Treat serve:false, timeout, and errors as no-render.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContextEnvelope"},"example":{"message":"시니어 반려견에게 줄 부드러운 사료를 찾고 있어요","locale":"ko","country":"KR","audience":{"age_band":"18_plus","contextual_offer_consent":true},"native_surface":{"clickable":true,"disclosure_capable":true}}}}},"responses":{"200":{"description":"Served offer or successful no-fill","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/DecideServe"},{"$ref":"#/components/schemas/DecideNoFill"}]},"examples":{"serve":{"value":{"serve":true,"request_id":"req_01","decision_id":"dec_01","offer_id":"snp_01EXAMPLEOFFER","expires_at":"2026-09-10T12:30:00.000Z","disclosure":"광고","advertiser":"Example Pet","link":"https://knobase.com/r/tok_example","title":"시니어 반려견을 위한 부드러운 식사 옵션","description":"제품 정보와 원재료를 확인해보세요.","cta":"제품 보기","reason_codes":["MATCHED"]}},"noFill":{"value":{"serve":false,"request_id":"req_02","decision_id":"dec_02","reason_codes":["NO_ELIGIBLE_OFFER"],"retry_after_seconds":0}}}}}},"400":{"description":"Invalid envelope or forbidden identity field","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"429":{"description":"Rate limited (60/min/IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}}}}},"/v1/offers/affiliate":{"post":{"tags":["Affiliate"],"summary":"Decide a Travelpayouts affiliate offer","description":"Parallel to decide. Returns a direct Travelpayouts tracking URL or serve:false. Does not rewrite the organic answer. Does not use /r/{token}.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Affiliate fill or successful no-fill"},"401":{"description":"Authentication failed"}}}},"/v1/events/click-intent":{"post":{"tags":["Events"],"summary":"Record a non-blocking affiliate click intent","description":"Operational analytics only. Capability is impression_token. Never determines revenue.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["impression_token","event_id"],"properties":{"impression_token":{"type":"string"},"event_id":{"type":"string"},"occurred_at":{"type":"string"}}}}}},"responses":{"200":{"description":"Recorded (billable: false)"},"404":{"description":"unknown_impression"}}}},"/r/{token}":{"get":{"tags":["Redirect"],"summary":"Redirect a tracked click","description":"Public browser redirect. Use the link returned by decide. No Bearer auth.","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect to the allowlisted destination"},"400":{"description":"Invalid token or destination"}}}},"/v1/events/rendered":{"post":{"tags":["Events"],"summary":"Record offer_rendered. Prefer Idempotency-Key header.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":80}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImpressionEvent"},"example":{"offer_snapshot_id":"snp_01EXAMPLEOFFER","decision_id":"dec_01","type":"offer_rendered","idempotency_key":"idemp_rendered_01"}}}},"responses":{"200":{"description":"Event recorded (billable: false)"},"400":{"description":"invalid_event"},"401":{"description":"Authentication failed"},"404":{"description":"unknown_snapshot"}}}},"/v1/events/qualified-impression":{"post":{"tags":["Events"],"summary":"Record qualified_impression. Prefer Idempotency-Key header.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":80}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImpressionEvent"},"example":{"offer_snapshot_id":"snp_01EXAMPLEOFFER","decision_id":"dec_01","type":"qualified_impression","idempotency_key":"idemp_qualified_01"}}}},"responses":{"200":{"description":"Event recorded (billable: false)"},"400":{"description":"invalid_event"},"401":{"description":"Authentication failed"},"404":{"description":"unknown_snapshot"}}}},"/v1/events/impression":{"post":{"tags":["Events"],"summary":"Alias for rendered or qualified_impression until first-party clients migrate","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImpressionEvent"},"examples":{"rendered":{"value":{"offer_snapshot_id":"snp_01EXAMPLEOFFER","decision_id":"dec_01","type":"offer_rendered","idempotency_key":"idemp_rendered_01"}},"qualified":{"value":{"offer_snapshot_id":"snp_01EXAMPLEOFFER","decision_id":"dec_01","type":"qualified_impression","idempotency_key":"idemp_qualified_01"}}}}}},"responses":{"200":{"description":"Event recorded (billable: false)"},"400":{"description":"invalid_event"},"401":{"description":"Authentication failed"},"404":{"description":"unknown_snapshot"}}}},"/v1/events/conversion":{"post":{"tags":["Events"],"summary":"Record a signed conversion","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionEvent"},"example":{"offer_snapshot_id":"snp_01EXAMPLEOFFER","decision_id":"dec_01","timestamp":1757491200000,"nonce":"nonce_example_01","signature":"aaaaaaaaaaaaaaaa"}}}},"responses":{"200":{"description":"Event recorded (billable: false, ledger_written: false)"},"400":{"description":"invalid_conversion or expired_conversion"},"401":{"description":"Authentication failed or invalid_signature"}}}},"/v1/decisions/{id}":{"get":{"tags":["Decisions"],"summary":"Read decision metadata for the authenticated app","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Decision metadata"},"401":{"description":"Authentication failed"},"404":{"description":"not_found"}}}}}}