{"openapi":"3.1.1","info":{"title":"TANKA Ambassador Attribution API","version":"1.0.0","description":"Server integration API. POST uses dynamic HMAC signatures; GET uses a dedicated Bearer Token. Examples are illustrative. HTTP 202 indicates persisted receipt only; rewards are determined asynchronously."},"servers":[{"url":"https://ambassador.tanka.ai"}],"externalDocs":{"url":"https://ambassador.tanka.ai/docs","description":"Integration guide and signing examples"},"tags":[{"name":"Postback"},{"name":"Referral links"}],"paths":{"/integration/v1/events":{"post":{"operationId":"receiveTankaUserState","tags":["Postback"],"summary":"Send the complete user state","description":"Sign each request with HMAC-SHA256(secret, timestamp + '.' + the raw UTF-8 body). Attribution is matched by the referral_code issued by TANKA and registered by an administrator. The three internal IDs may be omitted or null; if supplied, they must match the registration. state_version increases per user. Retries retain event_id and content. See /docs for consistency rules.","security":[{"HmacSignature":[]}],"parameters":[{"name":"X-Tanka-Key-Id","in":"header","required":true,"description":"The issued key identifier","schema":{"type":"string","minLength":1}},{"name":"X-Tanka-Timestamp","in":"header","required":true,"description":"Current Unix seconds. Allowed clock tolerance: 300 seconds","schema":{"type":"string","pattern":"^[0-9]{10,12}$"}}],"requestBody":{"required":true,"description":"Complete snapshot. Maximum 65536 UTF-8 bytes. Unknown fields are rejected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TankaEvent"},"examples":{"signup":{"summary":"signup (illustrative data)","value":{"schema_version":"1.0","event_id":"example.signup.001","event_type":"signup_completed","environment":"production","program_id":"tanka-jp-ambassador","user_id":"example-user-001","state_version":1,"occurred_at":"2026-09-08T00:03:00+09:00","state_updated_at":"2026-09-08T00:03:00+09:00","data":{"is_new_user":true,"registration_email":"example-user@example.invalid","counting_status":"valid","reason_code":null,"attribution":{"status":"attributed","ambassador_id":"11111111-1111-4111-8111-111111111111","referral_code":"JP-example-only","referral_link_id":"22222222-2222-4222-8222-222222222222","campaign_id":"33333333-3333-4333-8333-333333333333","touch_id":"example-touch-001","touched_at":"2026-09-08T00:01:00+09:00","bound_at":"2026-09-08T00:03:00+09:00","model":"last_click","window_days":30,"rule_version":"attr-v1"},"milestones":{"signup_at":"2026-09-08T00:03:00+09:00","first_link_completed_at":null},"first_link":null,"qualification_rule_version":"first-link-v1","correction":null}}},"firstLink":{"summary":"firstLink (illustrative data)","value":{"schema_version":"1.0","event_id":"example.first-link.001","event_type":"first_link_completed","environment":"production","program_id":"tanka-jp-ambassador","user_id":"example-user-001","state_version":2,"occurred_at":"2026-09-08T00:05:00+09:00","state_updated_at":"2026-09-08T00:05:00+09:00","data":{"is_new_user":true,"registration_email":"example-user@example.invalid","counting_status":"valid","reason_code":null,"attribution":{"status":"attributed","ambassador_id":"11111111-1111-4111-8111-111111111111","referral_code":"JP-example-only","referral_link_id":"22222222-2222-4222-8222-222222222222","campaign_id":"33333333-3333-4333-8333-333333333333","touch_id":"example-touch-001","touched_at":"2026-09-08T00:01:00+09:00","bound_at":"2026-09-08T00:03:00+09:00","model":"last_click","window_days":30,"rule_version":"attr-v1"},"milestones":{"signup_at":"2026-09-08T00:03:00+09:00","first_link_completed_at":"2026-09-08T00:05:00+09:00"},"first_link":{"event_id":"example-link-success-001","link_type":"calendar"},"qualification_rule_version":"first-link-v1","correction":null}}},"codeOnly":{"summary":"codeOnly (illustrative data)","value":{"schema_version":"1.0","event_id":"example.first-link.code-only","event_type":"first_link_completed","environment":"production","program_id":"tanka-jp-ambassador","user_id":"example-user-001","state_version":2,"occurred_at":"2026-09-08T00:05:00+09:00","state_updated_at":"2026-09-08T00:05:00+09:00","data":{"is_new_user":true,"registration_email":"example-user@example.invalid","counting_status":"valid","reason_code":null,"attribution":{"status":"attributed","ambassador_id":null,"referral_code":"JP-example-only","referral_link_id":null,"campaign_id":null,"touch_id":"example-touch-001","touched_at":"2026-09-08T00:01:00+09:00","bound_at":"2026-09-08T00:03:00+09:00","model":"last_click","window_days":30,"rule_version":"attr-v1"},"milestones":{"signup_at":"2026-09-08T00:03:00+09:00","first_link_completed_at":"2026-09-08T00:05:00+09:00"},"first_link":{"event_id":"example-link-success-001","link_type":"calendar"},"qualification_rule_version":"first-link-v1","correction":null}}},"pendingSignup":{"summary":"pendingSignup (illustrative data)","value":{"schema_version":"1.0","event_id":"example.signup.pending","event_type":"signup_completed","environment":"production","program_id":"tanka-jp-ambassador","user_id":"example-user-pending","state_version":1,"occurred_at":"2026-09-08T00:03:00+09:00","state_updated_at":"2026-09-08T00:03:00+09:00","data":{"is_new_user":true,"registration_email":"example-user@example.invalid","counting_status":"hold","reason_code":"attribution_unverified","attribution":{"status":"pending","ambassador_id":null,"referral_code":null,"referral_link_id":null,"campaign_id":null,"touch_id":null,"touched_at":null,"bound_at":null,"model":"last_click","window_days":30,"rule_version":"attr-v1"},"milestones":{"signup_at":"2026-09-08T00:03:00+09:00","first_link_completed_at":null},"first_link":null,"qualification_rule_version":"first-link-v1","correction":null}}},"attributionUpdated":{"summary":"attributionUpdated (illustrative data)","value":{"schema_version":"1.0","event_id":"example.attribution.confirmed","event_type":"attribution_updated","environment":"production","program_id":"tanka-jp-ambassador","user_id":"example-user-pending","state_version":2,"occurred_at":"2026-09-08T00:04:00+09:00","state_updated_at":"2026-09-08T00:04:00+09:00","data":{"is_new_user":true,"registration_email":"example-user@example.invalid","counting_status":"valid","reason_code":null,"attribution":{"status":"attributed","ambassador_id":"11111111-1111-4111-8111-111111111111","referral_code":"JP-example-only","referral_link_id":"22222222-2222-4222-8222-222222222222","campaign_id":"33333333-3333-4333-8333-333333333333","touch_id":"example-touch-001","touched_at":"2026-09-08T00:01:00+09:00","bound_at":"2026-09-08T00:04:00+09:00","model":"last_click","window_days":30,"rule_version":"attr-v1"},"milestones":{"signup_at":"2026-09-08T00:03:00+09:00","first_link_completed_at":null},"first_link":null,"qualification_rule_version":"first-link-v1","correction":null}}},"corrected":{"summary":"corrected (illustrative data)","value":{"schema_version":"1.0","event_id":"example.correction.001","event_type":"user_state_corrected","environment":"production","program_id":"tanka-jp-ambassador","user_id":"example-user-001","state_version":3,"occurred_at":"2026-09-08T00:08:00+09:00","state_updated_at":"2026-09-08T00:08:00+09:00","data":{"is_new_user":true,"registration_email":"example-user@example.invalid","counting_status":"invalid","reason_code":"internal_test","attribution":{"status":"attributed","ambassador_id":"11111111-1111-4111-8111-111111111111","referral_code":"JP-example-only","referral_link_id":"22222222-2222-4222-8222-222222222222","campaign_id":"33333333-3333-4333-8333-333333333333","touch_id":"example-touch-001","touched_at":"2026-09-08T00:01:00+09:00","bound_at":"2026-09-08T00:03:00+09:00","model":"last_click","window_days":30,"rule_version":"attr-v1"},"milestones":{"signup_at":"2026-09-08T00:03:00+09:00","first_link_completed_at":"2026-09-08T00:05:00+09:00"},"first_link":{"event_id":"example-link-success-001","link_type":"calendar"},"qualification_rule_version":"first-link-v1","correction":{"reason_code":"internal_test","reference_id":"example-audit-001","supersedes_state_version":2}}}}}}}},"responses":{"200":{"description":"The same event with identical content was already received.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Receipt"},"example":{"event_id":"example.first-link.001","status":"duplicate"}}}},"202":{"description":"Event persisted. This does not indicate completed reward processing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Receipt"},"example":{"event_id":"example.first-link.001","status":"accepted"}}}},"400":{"description":"Invalid JSON, invalid event fields or a cross-field constraint violation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"example":{"error":"INVALID_INPUT","message":"Invalid JSON, invalid event fields or a cross-field constraint violation.","request_id":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa","issues":[{"path":"","message":"Invalid JSON, invalid event fields or a cross-field constraint violation."}]}}}},"401":{"description":"Invalid key identifier, timestamp or signature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"},"example":{"error":"UNAUTHORIZED"}}}},"409":{"description":"Content differs for an existing event_id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"EVENT_ID_CONFLICT"}}}},"413":{"description":"The body exceeds the allowed size.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"INVALID_INPUT"}}}},"422":{"description":"ENVIRONMENT_MISMATCH or FUTURE_EVENT. Business timestamps cannot be more than 300 seconds ahead of the current time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"example":{"error":"ENVIRONMENT_MISMATCH","message":"ENVIRONMENT_MISMATCH or FUTURE_EVENT. Business timestamps cannot be more than 300 seconds ahead of the current time.","request_id":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa","issues":[{"path":"","message":"ENVIRONMENT_MISMATCH or FUTURE_EVENT. Business timestamps cannot be more than 300 seconds ahead of the current time."}]}}}},"503":{"description":"The inbox or service is unavailable. Retry with backoff. SERVICE_UNAVAILABLE or CONFIG_REQUIRED may also be returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"INBOX_UNAVAILABLE"}}}}}}},"/integration/v1/referral-links/{code}":{"get":{"operationId":"lookupReferralLink","tags":["Referral links"],"summary":"Optional: look up the referral mapping at the touchpoint time","security":[{"ReferralLookupToken":[]}],"parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_.:-]{1,64}$"}},{"name":"at","in":"query","required":true,"description":"The actual click time in RFC3339 with a timezone, at most 300 seconds ahead of the current time. Encode the plus sign in +09:00.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Returns the mapping. Check valid; false must not be treated as a valid touchpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferralMapping"}}}},"400":{"description":"Invalid referral code or timestamp format.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"example":{"error":"INVALID_INPUT","message":"Invalid referral code or timestamp format.","request_id":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa","issues":[{"path":"","message":"Invalid referral code or timestamp format."}]}}}},"401":{"description":"Invalid dedicated lookup Token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"},"example":{"error":"UNAUTHORIZED"}}}},"404":{"description":"The referral code does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"NOT_FOUND"}}}},"503":{"description":"The service is unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"SERVICE_UNAVAILABLE"}}}}}}}},"components":{"securitySchemes":{"HmacSignature":{"type":"apiKey","in":"header","name":"X-Tanka-Signature","description":"A dynamic HMAC-SHA256 digest as 64 lowercase hexadecimal characters. Never send the Secret itself. X-Tanka-Key-Id and X-Tanka-Timestamp are also required. The sender must generate the signature."},"ReferralLookupToken":{"type":"http","scheme":"bearer","description":"TANKA_LINK_LOOKUP_TOKEN dedicated to referral lookup."}},"schemas":{"TankaEvent":{"type":"object","properties":{"schema_version":{"type":"string","const":"1.0"},"event_id":{"type":"string","minLength":1,"maxLength":160,"pattern":"^[A-Za-z0-9_.:-]+$"},"event_type":{"type":"string","enum":["signup_completed","first_link_completed","attribution_updated","user_state_corrected"]},"environment":{"type":"string","const":"production"},"program_id":{"type":"string","minLength":1,"maxLength":160,"pattern":"^[A-Za-z0-9_.:-]+$","const":"tanka-jp-ambassador"},"user_id":{"type":"string","minLength":1,"maxLength":160,"pattern":"^[A-Za-z0-9_.:-]+$"},"state_version":{"type":"integer","minimum":1,"maximum":9007199254740991},"occurred_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"state_updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"data":{"type":"object","properties":{"is_new_user":{"type":"boolean"},"registration_email":{"description":"Email used at product signup, visible only to administrators. Optional for older senders. Ordinary omission or null preserves a known registration email; a differing value in an ordinary event is ignored (the first recorded value is kept); a higher-version correction can replace it or explicitly clear it with null.","anyOf":[{"type":"string","minLength":3,"maxLength":254,"pattern":"^[^\\s@\\x00-\\x1f\\x7f]+@[^\\s@\\x00-\\x1f\\x7f]+\\.[^\\s@\\x00-\\x1f\\x7f]+$"},{"type":"null"}]},"counting_status":{"type":"string","enum":["valid","hold","invalid"]},"reason_code":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}]},"attribution":{"type":"object","properties":{"status":{"type":"string","enum":["attributed","pending","unattributed"]},"ambassador_id":{"default":null,"anyOf":[{"type":"string","minLength":1,"maxLength":160,"pattern":"^[A-Za-z0-9_.:-]+$"},{"type":"null"}]},"referral_code":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9_.:-]{1,64}$"},{"type":"null"}]},"referral_link_id":{"default":null,"anyOf":[{"type":"string","minLength":1,"maxLength":160,"pattern":"^[A-Za-z0-9_.:-]+$"},{"type":"null"}]},"campaign_id":{"default":null,"anyOf":[{"type":"string","minLength":1,"maxLength":160,"pattern":"^[A-Za-z0-9_.:-]+$"},{"type":"null"}]},"touch_id":{"anyOf":[{"type":"string","minLength":1,"maxLength":160,"pattern":"^[A-Za-z0-9_.:-]+$"},{"type":"null"}]},"touched_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]},"bound_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]},"model":{"type":"string","maxLength":60},"window_days":{"type":"integer","minimum":0,"maximum":366},"rule_version":{"type":"string","minLength":1,"maxLength":160,"pattern":"^[A-Za-z0-9_.:-]+$"}},"required":["status","referral_code","touch_id","touched_at","bound_at","model","window_days","rule_version"],"additionalProperties":false},"milestones":{"type":"object","properties":{"signup_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"first_link_completed_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]}},"required":["signup_at","first_link_completed_at"],"additionalProperties":false},"first_link":{"anyOf":[{"type":"object","properties":{"event_id":{"type":"string","minLength":1,"maxLength":160,"pattern":"^[A-Za-z0-9_.:-]+$"},"link_type":{"type":"string","minLength":1,"maxLength":100}},"required":["event_id","link_type"],"additionalProperties":false},{"type":"null"}]},"qualification_rule_version":{"type":"string","minLength":1,"maxLength":160,"pattern":"^[A-Za-z0-9_.:-]+$"},"correction":{"anyOf":[{"type":"object","properties":{"reason_code":{"type":"string","minLength":1,"maxLength":160},"reference_id":{"type":"string","minLength":1,"maxLength":160,"pattern":"^[A-Za-z0-9_.:-]+$"},"supersedes_state_version":{"type":"integer","minimum":1,"maximum":9007199254740991}},"required":["reason_code","reference_id","supersedes_state_version"],"additionalProperties":false},{"type":"null"}]}},"required":["is_new_user","counting_status","reason_code","attribution","milestones","first_link","qualification_rule_version","correction"],"additionalProperties":false}},"required":["schema_version","event_id","event_type","environment","program_id","user_id","state_version","occurred_at","state_updated_at","data"],"additionalProperties":false,"description":"Generated from the actual Zod event schema. Cross-field business rules are validated separately by the server; see /docs."},"Receipt":{"type":"object","required":["event_id","status"],"properties":{"event_id":{"type":"string"},"status":{"type":"string","enum":["accepted","duplicate"]}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"message":{"type":"string","description":"Optional display message. Handle responses by the error field, independent of message wording or language."}}},"UnauthorizedError":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"const":"UNAUTHORIZED"}}},"ValidationError":{"type":"object","additionalProperties":false,"required":["error","message","request_id","issues"],"properties":{"error":{"type":"string"},"message":{"type":"string"},"request_id":{"type":"string","format":"uuid","description":"A receiver-generated identifier for investigation."},"issues":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["path","message"],"properties":{"path":{"type":"string","description":"Dot-separated field path, or an empty string for the entire request."},"message":{"type":"string"}}}}}},"ReferralMapping":{"type":"object","required":["program_id","ambassador_id","referral_link_id","referral_code","campaign_id","valid","checked_at","model","window_days","rule_version"],"properties":{"program_id":{"type":"string","const":"tanka-jp-ambassador"},"ambassador_id":{"type":"string","format":"uuid"},"referral_link_id":{"type":"string","format":"uuid"},"campaign_id":{"type":"string","format":"uuid"},"referral_code":{"type":"string"},"valid":{"type":"boolean"},"checked_at":{"type":"string","format":"date-time"},"model":{"type":"string","enum":["first_click","last_click"]},"window_days":{"type":"integer","minimum":0,"maximum":366},"rule_version":{"type":"string"}}}}}}