{
  "schema_version": "0.1.0",
  "name": "K-Work Trust",
  "description": "HTTPS API for AI agents that validate and normalize Korean business records before workflow actions.",
  "audience": [
    "autonomous agents",
    "agent builders",
    "bot operators",
    "workflow automation systems"
  ],
  "base_url": "https://k-work-trust-api.fly.dev",
  "status_url": "https://k-work-trust-api.fly.dev/health",
  "readiness_url": "https://k-work-trust-api.fly.dev/v1/agent/readiness",
  "openapi_url": "https://k-work-trust-api.fly.dev/openapi.json",
  "skill_url": "https://k-work-trust-api.fly.dev/skill.md",
  "llms_txt_url": "https://k-work-trust-api.fly.dev/llms.txt",
  "mcp_url": "https://k-work-trust-api.fly.dev/mcp",
  "mcp": {
    "transport": "streamable-http",
    "url": "https://k-work-trust-api.fly.dev/mcp",
    "auth": {
      "type": "bearer",
      "header": "Authorization: Bearer <kwt_api_key>",
      "required_for": [
        "tools/call"
      ],
      "not_required_for": [
        "initialize",
        "tools/list"
      ]
    },
    "supports": [
      "initialize",
      "tools/list",
      "tools/call"
    ],
    "sse_streams_enabled": false,
    "quota_policy": "tools/call consumes monthly request quota; initialize and tools/list do not."
  },
  "authenticated_session_url": "https://k-work-trust-api.fly.dev/v1/auth/whoami",
  "auth": {
    "type": "bearer",
    "header": "Authorization: Bearer <kwt_api_key>",
    "key_prefix": "kwt_"
  },
  "self_serve_signup": {
    "enabled": true,
    "mode": "provisional_key_or_email_verification_with_sha256_proof_of_work",
    "status_endpoint": "https://k-work-trust-api.fly.dev/v1/agent/signup/status",
    "proof_of_work": {
      "algorithm": "sha256",
      "digest_encoding": "hex",
      "input_template": "${nonce}:${subject}:${solution}",
      "difficulty_rule": "The hex digest must start with '0' repeated difficulty_hex_prefix_zeros times.",
      "solution_field": "proof.solution",
      "challenge_field": "proof.challenge",
      "max_solution_length": 160,
      "challenge_ttl_seconds": 300,
      "email_signup_difficulty_hex_prefix_zeros": 4,
      "provisional_signup_difficulty_hex_prefix_zeros": 4
    },
    "provisional": {
      "description": "For agents without an inbox. Issues an ultra-low-quota key after proof-of-work only.",
      "challenge_endpoint": "https://k-work-trust-api.fly.dev/v1/agent/signup/provisional/challenge?agent_label=<agent-label>",
      "issue_endpoint": "https://k-work-trust-api.fly.dev/v1/agent/signup/provisional",
      "proof_subject": "The returned subject from the challenge response, derived from agent_label, agent_id, or agent_url.",
      "default_quota": {
        "rate_limit_rpm": 1,
        "monthly_request_quota": 20
      },
      "official_sources": "disabled_by_default_until_email_verified_or_human_approved",
      "upgrade_request_code_endpoint": "https://k-work-trust-api.fly.dev/v1/agent/signup/provisional/upgrade/request-code",
      "upgrade_verify_endpoint": "https://k-work-trust-api.fly.dev/v1/agent/signup/provisional/upgrade/verify"
    },
    "email_verified": {
      "description": "For agents or operators with an inbox. Issues or upgrades to a higher low-quota key.",
      "challenge_endpoint": "https://k-work-trust-api.fly.dev/v1/agent/signup/challenge?email=<agent-or-operator-email>",
      "request_code_endpoint": "https://k-work-trust-api.fly.dev/v1/agent/signup/request-code",
      "verify_endpoint": "https://k-work-trust-api.fly.dev/v1/agent/signup/verify",
      "proof_subject": "The normalized email returned from the challenge response."
    },
    "challenge_endpoint": "https://k-work-trust-api.fly.dev/v1/agent/signup/challenge?email=<agent-or-operator-email>",
    "request_code_endpoint": "https://k-work-trust-api.fly.dev/v1/agent/signup/request-code",
    "verify_endpoint": "https://k-work-trust-api.fly.dev/v1/agent/signup/verify",
    "key_visibility": "The plaintext API key is returned once after verification."
  },
  "recommended_first_call": {
    "method": "POST",
    "path": "/v1/vendor-onboarding/validate",
    "description": "Use before an agent creates or updates a Korean vendor, customer, invoice, CRM, or ecommerce business record.",
    "body_example": {
      "company_name": "Test Company",
      "registration_number": "1234567891",
      "phone_number": "01012345678"
    },
    "response_contract": {
      "success_fields": [
        "request_id",
        "tool",
        "result.status",
        "result.decision",
        "result.blocking_issues",
        "result.warnings",
        "result.evidence",
        "result.agent_next_action"
      ],
      "decision_meanings": {
        "register_vendor": "Proceed only with normalized_record and retained evidence.",
        "request_human_review": "Pause downstream writes and route warnings/evidence to a human reviewer.",
        "do_not_proceed": "Abort downstream workflow until blocking_issues are corrected."
      },
      "failure_mode_field": "failure_modes",
      "escalation_contract": "Use failure_modes to choose retry, abort, or human/operator escalation without guessing from HTTP status alone."
    }
  },
  "response_contract": {
    "success_fields": [
      "request_id",
      "tool",
      "result.status",
      "result.decision",
      "result.blocking_issues",
      "result.warnings",
      "result.evidence",
      "result.agent_next_action"
    ],
    "decision_meanings": {
      "register_vendor": "Proceed only with normalized_record and retained evidence.",
      "request_human_review": "Pause downstream writes and route warnings/evidence to a human reviewer.",
      "do_not_proceed": "Abort downstream workflow until blocking_issues are corrected."
    },
    "failure_mode_field": "failure_modes",
    "escalation_contract": "Use failure_modes to choose retry, abort, or human/operator escalation without guessing from HTTP status alone."
  },
  "failure_modes": [
    {
      "code": "UNAUTHORIZED",
      "applies_to": [
        "authenticated_api",
        "whoami"
      ],
      "http_status": 401,
      "category": "auth_failure",
      "retry": "do_not_retry_same_key",
      "agent_next_action": "Abort the protected call, verify the key with /v1/auth/whoami, and obtain a valid key through self-serve signup or the operator.",
      "escalation": "human_or_operator_if_the_agent_expected_this_key_to_be_active",
      "safe_to_log": [
        "request_id",
        "error.code"
      ],
      "do_not_log": [
        "plaintext_api_key",
        "private_records",
        "secrets"
      ]
    },
    {
      "code": "RATE_LIMITED",
      "applies_to": [
        "authenticated_api",
        "signup"
      ],
      "http_status": 429,
      "category": "temporary_limit",
      "retry": "retry_after_retry_after_seconds",
      "agent_next_action": "Wait for retry_after_seconds before retrying. If the workflow is urgent or repeated rate limits occur, escalate instead of looping.",
      "escalation": "human_review_or_alternative_route_for_time_sensitive_workflows",
      "safe_to_log": [
        "request_id",
        "error.code",
        "retry_after_seconds"
      ],
      "do_not_log": [
        "plaintext_api_key",
        "private_records",
        "secrets"
      ]
    },
    {
      "code": "QUOTA_EXCEEDED",
      "applies_to": [
        "authenticated_api"
      ],
      "http_status": 429,
      "category": "quota_exhausted",
      "retry": "do_not_retry_until_resets_at",
      "agent_next_action": "Stop automated calls for this key until resets_at or ask an operator for review. Do not request a manual key in public channels.",
      "escalation": "operator_review_required_for_quota_change",
      "safe_to_log": [
        "request_id",
        "error.code",
        "quota.limit",
        "quota.used",
        "quota.resets_at"
      ],
      "do_not_log": [
        "plaintext_api_key",
        "private_records",
        "secrets"
      ]
    },
    {
      "code": "VALIDATION_BLOCKED",
      "applies_to": [
        "workflow_response"
      ],
      "http_status": 200,
      "category": "business_rule_block",
      "retry": "retry_only_after_correcting_input",
      "agent_next_action": "Do not proceed with the workflow action. Preserve blocking_issues and evidence, then collect corrected fields or ask a human reviewer.",
      "escalation": "human_review_if_the_record_is_business_critical",
      "safe_to_log": [
        "request_id",
        "status",
        "decision",
        "blocking_issues",
        "warnings"
      ],
      "do_not_log": [
        "plaintext_api_key",
        "private_records",
        "secrets"
      ]
    },
    {
      "code": "MANUAL_REVIEW",
      "applies_to": [
        "workflow_response"
      ],
      "http_status": 200,
      "category": "needs_human_judgment",
      "retry": "do_not_auto_retry_without_new_information",
      "agent_next_action": "Route the normalized record, warnings, and evidence to a human reviewer before creating or updating downstream records.",
      "escalation": "human_review_required_before_downstream_write",
      "safe_to_log": [
        "request_id",
        "status",
        "decision",
        "warnings",
        "evidence"
      ],
      "do_not_log": [
        "plaintext_api_key",
        "private_records",
        "secrets"
      ]
    },
    {
      "code": "SOURCE_UNAVAILABLE",
      "applies_to": [
        "workflow_response",
        "official_sources"
      ],
      "http_status": 200,
      "category": "external_source_unavailable",
      "retry": "retry_later_or_continue_local_only_if_policy_allows",
      "agent_next_action": "Use local validation only when acceptable. If official-source evidence is required, pause the workflow and escalate with request_id and evidence.",
      "escalation": "human_or_operator_if_official_source_evidence_is_required",
      "safe_to_log": [
        "request_id",
        "external_status",
        "warnings",
        "evidence"
      ],
      "do_not_log": [
        "plaintext_api_key",
        "private_records",
        "secrets"
      ]
    },
    {
      "code": "PROOF_OF_WORK_FAILED",
      "applies_to": [
        "signup"
      ],
      "http_status": 403,
      "category": "signup_challenge_failure",
      "retry": "request_fresh_challenge_and_solve_contract",
      "agent_next_action": "Request a fresh challenge, solve sha256(nonce + ':' + subject + ':' + solution), and avoid repeated blind retries.",
      "escalation": "only_if_repeated_failures_indicate_onboarding_blocker",
      "safe_to_log": [
        "request_id",
        "error.code"
      ],
      "do_not_log": [
        "plaintext_api_key",
        "private_records",
        "secrets"
      ]
    },
    {
      "code": "SIGNUP_RATE_LIMITED",
      "applies_to": [
        "signup"
      ],
      "http_status": 429,
      "category": "signup_limit",
      "retry": "wait_before_requesting_another_challenge_or_mutation",
      "agent_next_action": "Wait before continuing signup. Do not ask for a pasted plaintext key; use the self-serve flow after the limit resets.",
      "escalation": "operator_review_only_for_repeated_legitimate_tester_blockers",
      "safe_to_log": [
        "request_id",
        "error.code"
      ],
      "do_not_log": [
        "plaintext_api_key",
        "private_records",
        "secrets"
      ]
    },
    {
      "code": "ABUSE_GUARD_BLOCKED",
      "applies_to": [
        "authenticated_api",
        "workflow_request"
      ],
      "http_status": 403,
      "category": "misuse_or_sensitive_input_guard",
      "retry": "do_not_retry_same_payload",
      "agent_next_action": "Stop the request. Remove secrets, sensitive personal identifiers, bulk records, or enumeration-like input before retrying with one synthetic or authorized business record.",
      "escalation": "operator_review_if_the_agent_believes_the_block_is_false_positive",
      "safe_to_log": [
        "request_id",
        "error.code",
        "abuse.reason"
      ],
      "do_not_log": [
        "plaintext_api_key",
        "private_records",
        "secrets",
        "personal_identifiers"
      ]
    }
  ],
  "abuse_guard": {
    "enabled": true,
    "behavior_based": true,
    "does_not_infer_nationality": true,
    "low_trust_max_records_per_request": 1,
    "low_trust_max_business_number_like_identifiers": 4,
    "blocks": [
      "plaintext API keys or bearer tokens in request bodies",
      "personal identifier patterns such as resident registration or passport fields",
      "bulk or batch payloads from low-trust/provisional keys",
      "many distinct business-number-like identifiers from low-trust/provisional keys"
    ],
    "operator_controls": [
      "KWT_ABUSE_GUARD_ENABLED=false disables the guard temporarily",
      "KWT_REJECT_PROVISIONAL_KEYS=true rejects existing provisional keys",
      "KWT_PROVISIONAL_ALLOW_OFFICIAL_SOURCES=false keeps provisional keys local-only"
    ]
  },
  "safe_test_payloads": {
    "vendor_onboarding": {
      "company_name": "Test Company",
      "registration_number": "1234567891",
      "phone_number": "01012345678"
    }
  },
  "endpoints": [
    {
      "method": "GET",
      "path": "/v1/agent/readiness",
      "auth_required": false,
      "purpose": "Check whether the deployment is ready for autonomous or invited agent use."
    },
    {
      "method": "GET",
      "path": "/v1/auth/whoami",
      "auth_required": true,
      "purpose": "Verify a key and inspect trust level, quotas, and official-source policy without consuming monthly quota."
    },
    {
      "method": "GET",
      "path": "/v1/tools",
      "auth_required": true,
      "purpose": "List callable tools."
    },
    {
      "method": "POST",
      "path": "/mcp",
      "auth_required": "tools/call only",
      "purpose": "Remote MCP Streamable HTTP endpoint. initialize and tools/list are public; tools/call requires a bearer key."
    },
    {
      "method": "POST",
      "path": "/v1/tools/call",
      "auth_required": true,
      "purpose": "Call a tool dynamically by name."
    },
    {
      "method": "POST",
      "path": "/v1/vendor-onboarding/validate",
      "auth_required": true,
      "purpose": "Return a workflow decision, normalized record, issues, warnings, evidence, and next action."
    },
    {
      "method": "POST",
      "path": "/v1/payment-or-invoice-release/validate",
      "auth_required": true,
      "purpose": "Gate payment, invoice, settlement, or purchase release with amount policy, required fixes, and a human review packet."
    }
  ],
  "agent_policy": [
    "Use synthetic data, public test data, or records the agent is authorized to process.",
    "Do not treat responses as legal, tax, accounting, or official endorsement advice.",
    "Preserve blocking issues and evidence when escalating to a human.",
    "Do not expose the API key in public prompts, posts, logs, or tool outputs."
  ]
}