{"openapi":"3.1.0","info":{"title":"REPUTATION.md API","version":"1.1","description":"A plain file format for an agent's own experience with other agents, services, stores and firms: who they are, what happened and when, and the rules that turn those events into a score and a tier. Read-only tools score, rank, decay, merge, lint, template and parse the file over HTTP and MCP, find the distance to a tier, and make a hashed summary another agent can check; four starters tune the rules for stores, agent services, data providers and contractors. Every number comes from your file or your request. Read-only, no key, nothing stored. Use at your own risk. reputation.md is provided as is, without warranty. Information here may be inaccurate, incomplete or not current, and is not verified; figures are estimates from the numbers you send and the formulas stated. Nothing here is legal, financial, credit, security or professional advice; nothing here verifies anyone's identity, certifies anyone or is a finding of fault. reputation.md never blocks, pays, contacts or reports anyone itself. Check everything yourself before you act on it.","termsOfService":"https://reputation.md/terms","license":{"name":"MIT","identifier":"MIT"}},"servers":[{"url":"https://reputation.md"}],"paths":{"/reputation.md":{"get":{"operationId":"getSkill","summary":"The REPUTATION.md skill as Markdown. Add a preset or any setting to write your settings in; notes on clamped or ignored values come back in the X-Settings-Notes header.","parameters":[{"name":"preset","in":"query","required":false,"schema":{"type":"string","enum":["core","recommended","strict","forgiving"]}},{"name":"w_delivered","in":"query","required":false,"description":"Delivered (points). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":-10,"maximum":10}},{"name":"w_honored","in":"query","required":false,"description":"Honored (points). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":-10,"maximum":10}},{"name":"w_resolved","in":"query","required":false,"description":"Resolved (points). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":-10,"maximum":10}},{"name":"w_late","in":"query","required":false,"description":"Late (points). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":-10,"maximum":10}},{"name":"w_refunded","in":"query","required":false,"description":"Refunded (points). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":-10,"maximum":10}},{"name":"w_disputed","in":"query","required":false,"description":"Disputed (points). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":-10,"maximum":10}},{"name":"w_failed","in":"query","required":false,"description":"Failed (points). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":-10,"maximum":10}},{"name":"w_breached","in":"query","required":false,"description":"Breached (points). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":-10,"maximum":10}},{"name":"half_life_days","in":"query","required":false,"description":"Half-life (days). Default 90. Out-of-range values are clamped.","schema":{"type":"integer","minimum":7,"maximum":730}},{"name":"min_events","in":"query","required":false,"description":"Events before a score counts (events). Default 3. Out-of-range values are clamped.","schema":{"type":"integer","minimum":1,"maximum":20}},{"name":"review_days","in":"query","required":false,"description":"Review interval (days). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"integer","minimum":1,"maximum":365}},{"name":"trusted_min","in":"query","required":false,"description":"Trusted from a score of (points). Default 75. Out-of-range values are clamped.","schema":{"type":"integer","minimum":0,"maximum":100}},{"name":"standard_min","in":"query","required":false,"description":"Standard from a score of (points). Default 50. Capped at trusted_min. Out-of-range values are clamped.","schema":{"type":"integer","minimum":0,"maximum":100}},{"name":"watch_min","in":"query","required":false,"description":"Watch from a score of (blocked below) (points). Default 25. Capped at standard_min. Out-of-range values are clamped.","schema":{"type":"integer","minimum":0,"maximum":100}},{"name":"trusted_spend","in":"query","required":false,"description":"Trusted: spend without asking (per task). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":0,"maximum":1000000}},{"name":"standard_spend","in":"query","required":false,"description":"Standard: spend without asking (per task). Capped at trusted_spend. Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":0,"maximum":1000000}}],"responses":{"200":{"description":"The skill","content":{"text/markdown":{"schema":{"type":"string"}}}}}}},"/api/v1/settings":{"get":{"operationId":"listSettings","summary":"Every setting (group, kind, unit, range, options, default) and the presets.","responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}}}}},"/api/v1/score_counterparty":{"get":{"operationId":"scoreCounterpartyGet","summary":"Score one counterparty from its events","description":"A 0 to 100 score for one counterparty from the dated events you send, or from a REPUTATION.md file and an id. Each event's weight decays with a half-life; positive and negative evidence are summed; the score is 50 plus 50 times the net evidence over the total evidence plus a neutral prior of 2, so it starts at 50 and needs evidence to move. Returns the breakdown per event type, the effective event count, a confidence from that count, whether the score counts yet (min_events) and the tier it lands in under your rules, with what that tier allows. Rules come from the defaults, then the file's Rules section, then your arguments. Uses only what you send; it fetches nothing, verifies no one, and a low score is a reading of your own record, not a finding of fault.","parameters":[{"name":"counterparty","in":"query","required":false,"description":"The counterparty's id: a handle like agent:courier-12, a domain or a URL. Required with text; a label otherwise.","schema":{"type":"string"}},{"name":"events","in":"query","required":false,"description":"Events for one counterparty: [{ date (YYYY-MM-DD), type (delivered | honored | resolved | late | refunded | disputed | failed | breached), amount (optional, a plain number), note (optional) }]. Up to 200. URL-encoded JSON.","schema":{"type":"string"}},{"name":"text","in":"query","required":false,"description":"A whole REPUTATION.md file, as a string.","schema":{"type":"string"}},{"name":"as_of","in":"query","required":false,"description":"The date to score as of (YYYY-MM-DD). Default: today. Ages and decay are measured from it.","schema":{"type":"string"}},{"name":"half_life_days","in":"query","required":false,"description":"An event's weight halves every this many days. Default 90, or the file's rule.","schema":{"type":"number","minimum":1,"maximum":3650}},{"name":"min_events","in":"query","required":false,"description":"Events needed before a score counts. Default 3, or the file's rule.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"weights","in":"query","required":false,"description":"Weight per event type, like {\"delivered\": 1, \"breached\": -3}; types you leave out keep the default or the file's rule. Defaults: delivered 1, honored 1, resolved 0.5, late -0.5, refunded -0.5, disputed -1, failed -2, breached -3. URL-encoded JSON.","schema":{"type":"string"}},{"name":"trusted_min","in":"query","required":false,"description":"Minimum score for the trusted tier. Default 75.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"standard_min","in":"query","required":false,"description":"Minimum score for the standard tier. Default 50.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"watch_min","in":"query","required":false,"description":"Minimum score for the watch tier; below it is blocked. Default 25.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"trusted_spend","in":"query","required":false,"description":"What a trusted counterparty may be paid per task without asking. Default 500.","schema":{"type":"number","minimum":0,"maximum":1000000000}},{"name":"standard_spend","in":"query","required":false,"description":"What a standard counterparty may be paid per task without asking. Default 100.","schema":{"type":"number","minimum":0,"maximum":1000000000}}],"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"scoreCounterparty","summary":"Score one counterparty from its events","description":"A 0 to 100 score for one counterparty from the dated events you send, or from a REPUTATION.md file and an id. Each event's weight decays with a half-life; positive and negative evidence are summed; the score is 50 plus 50 times the net evidence over the total evidence plus a neutral prior of 2, so it starts at 50 and needs evidence to move. Returns the breakdown per event type, the effective event count, a confidence from that count, whether the score counts yet (min_events) and the tier it lands in under your rules, with what that tier allows. Rules come from the defaults, then the file's Rules section, then your arguments. Uses only what you send; it fetches nothing, verifies no one, and a low score is a reading of your own record, not a finding of fault.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"counterparty":{"type":"string","maxLength":120,"description":"The counterparty's id: a handle like agent:courier-12, a domain or a URL. Required with text; a label otherwise."},"events":{"type":"array","maxItems":200,"items":{"type":"object","properties":{"date":{"type":"string"},"type":{"type":"string","enum":["delivered","honored","resolved","late","refunded","disputed","failed","breached"]},"amount":{"type":"number"},"note":{"type":"string"}},"required":["date","type"]},"description":"Events for one counterparty: [{ date (YYYY-MM-DD), type (delivered | honored | resolved | late | refunded | disputed | failed | breached), amount (optional, a plain number), note (optional) }]. Up to 200."},"text":{"type":"string","maxLength":200000,"description":"A whole REPUTATION.md file, as a string."},"as_of":{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The date to score as of (YYYY-MM-DD). Default: today. Ages and decay are measured from it."},"half_life_days":{"type":"number","minimum":1,"maximum":3650,"description":"An event's weight halves every this many days. Default 90, or the file's rule."},"min_events":{"type":"integer","minimum":1,"maximum":100,"description":"Events needed before a score counts. Default 3, or the file's rule."},"weights":{"type":"object","description":"Weight per event type, like {\"delivered\": 1, \"breached\": -3}; types you leave out keep the default or the file's rule. Defaults: delivered 1, honored 1, resolved 0.5, late -0.5, refunded -0.5, disputed -1, failed -2, breached -3.","properties":{"delivered":{"type":"number","minimum":-10,"maximum":10},"honored":{"type":"number","minimum":-10,"maximum":10},"resolved":{"type":"number","minimum":-10,"maximum":10},"late":{"type":"number","minimum":-10,"maximum":10},"refunded":{"type":"number","minimum":-10,"maximum":10},"disputed":{"type":"number","minimum":-10,"maximum":10},"failed":{"type":"number","minimum":-10,"maximum":10},"breached":{"type":"number","minimum":-10,"maximum":10}}},"trusted_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the trusted tier. Default 75."},"standard_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the standard tier. Default 50."},"watch_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the watch tier; below it is blocked. Default 25."},"trusted_spend":{"type":"number","minimum":0,"maximum":1000000000,"description":"What a trusted counterparty may be paid per task without asking. Default 500."},"standard_spend":{"type":"number","minimum":0,"maximum":1000000000,"description":"What a standard counterparty may be paid per task without asking. Default 100."}}},"example":{"counterparty":"shop.example","text":"---\nreputation: 1\nupdated: 2026-10-22\n---\n## Counterparties\n- shop.example · store · parts\n- agent:courier-12 · agent · delivery\n## Events\n- 2026-09-21 · shop.example · late · 80\n- 2026-10-03 · shop.example · delivered · 120\n- 2026-10-20 · shop.example · delivered · 45\n- 2026-10-10 · agent:courier-12 · failed · 15\n","as_of":"2026-10-22"}}}},"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body over 64 KB"}}}},"/api/v1/rank_counterparties":{"get":{"operationId":"rankCounterpartiesGet","summary":"Score and rank every counterparty","description":"Scores every counterparty in a REPUTATION.md file (or in a list you send) with the same formula as score_counterparty, under the same rules, and sorts them by score, then confidence. Returns the ranking with each tier and what it allows, a count per tier, and the counterparties that are unrated or blocked. Rules come from the defaults, then the file's Rules section, then your arguments. Uses only what you send; it fetches nothing, verifies no one, and the order is a reading of your own record, not a judgment of anyone.","parameters":[{"name":"text","in":"query","required":false,"description":"A whole REPUTATION.md file, as a string.","schema":{"type":"string"}},{"name":"counterparties","in":"query","required":false,"description":"Instead of text: [{ id, kind (optional), events: [{ date, type, amount }] }]. Up to 200. URL-encoded JSON.","schema":{"type":"string"}},{"name":"as_of","in":"query","required":false,"description":"The date to score as of (YYYY-MM-DD). Default: today. Ages and decay are measured from it.","schema":{"type":"string"}},{"name":"half_life_days","in":"query","required":false,"description":"An event's weight halves every this many days. Default 90, or the file's rule.","schema":{"type":"number","minimum":1,"maximum":3650}},{"name":"min_events","in":"query","required":false,"description":"Events needed before a score counts. Default 3, or the file's rule.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"weights","in":"query","required":false,"description":"Weight per event type, like {\"delivered\": 1, \"breached\": -3}; types you leave out keep the default or the file's rule. Defaults: delivered 1, honored 1, resolved 0.5, late -0.5, refunded -0.5, disputed -1, failed -2, breached -3. URL-encoded JSON.","schema":{"type":"string"}},{"name":"trusted_min","in":"query","required":false,"description":"Minimum score for the trusted tier. Default 75.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"standard_min","in":"query","required":false,"description":"Minimum score for the standard tier. Default 50.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"watch_min","in":"query","required":false,"description":"Minimum score for the watch tier; below it is blocked. Default 25.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"trusted_spend","in":"query","required":false,"description":"What a trusted counterparty may be paid per task without asking. Default 500.","schema":{"type":"number","minimum":0,"maximum":1000000000}},{"name":"standard_spend","in":"query","required":false,"description":"What a standard counterparty may be paid per task without asking. Default 100.","schema":{"type":"number","minimum":0,"maximum":1000000000}}],"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"rankCounterparties","summary":"Score and rank every counterparty","description":"Scores every counterparty in a REPUTATION.md file (or in a list you send) with the same formula as score_counterparty, under the same rules, and sorts them by score, then confidence. Returns the ranking with each tier and what it allows, a count per tier, and the counterparties that are unrated or blocked. Rules come from the defaults, then the file's Rules section, then your arguments. Uses only what you send; it fetches nothing, verifies no one, and the order is a reading of your own record, not a judgment of anyone.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","maxLength":200000,"description":"A whole REPUTATION.md file, as a string."},"counterparties":{"type":"array","maxItems":200,"items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["agent","service","store","firm"]},"events":{"type":"array","maxItems":200,"items":{"type":"object","properties":{"date":{"type":"string"},"type":{"type":"string","enum":["delivered","honored","resolved","late","refunded","disputed","failed","breached"]},"amount":{"type":"number"},"note":{"type":"string"}},"required":["date","type"]},"description":"Events for one counterparty: [{ date (YYYY-MM-DD), type (delivered | honored | resolved | late | refunded | disputed | failed | breached), amount (optional, a plain number), note (optional) }]. Up to 200."}},"required":["id","events"]},"description":"Instead of text: [{ id, kind (optional), events: [{ date, type, amount }] }]. Up to 200."},"as_of":{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The date to score as of (YYYY-MM-DD). Default: today. Ages and decay are measured from it."},"half_life_days":{"type":"number","minimum":1,"maximum":3650,"description":"An event's weight halves every this many days. Default 90, or the file's rule."},"min_events":{"type":"integer","minimum":1,"maximum":100,"description":"Events needed before a score counts. Default 3, or the file's rule."},"weights":{"type":"object","description":"Weight per event type, like {\"delivered\": 1, \"breached\": -3}; types you leave out keep the default or the file's rule. Defaults: delivered 1, honored 1, resolved 0.5, late -0.5, refunded -0.5, disputed -1, failed -2, breached -3.","properties":{"delivered":{"type":"number","minimum":-10,"maximum":10},"honored":{"type":"number","minimum":-10,"maximum":10},"resolved":{"type":"number","minimum":-10,"maximum":10},"late":{"type":"number","minimum":-10,"maximum":10},"refunded":{"type":"number","minimum":-10,"maximum":10},"disputed":{"type":"number","minimum":-10,"maximum":10},"failed":{"type":"number","minimum":-10,"maximum":10},"breached":{"type":"number","minimum":-10,"maximum":10}}},"trusted_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the trusted tier. Default 75."},"standard_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the standard tier. Default 50."},"watch_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the watch tier; below it is blocked. Default 25."},"trusted_spend":{"type":"number","minimum":0,"maximum":1000000000,"description":"What a trusted counterparty may be paid per task without asking. Default 500."},"standard_spend":{"type":"number","minimum":0,"maximum":1000000000,"description":"What a standard counterparty may be paid per task without asking. Default 100."}}},"example":{"text":"---\nreputation: 1\nupdated: 2026-10-22\n---\n## Counterparties\n- shop.example · store · parts\n- agent:courier-12 · agent · delivery\n## Events\n- 2026-09-21 · shop.example · late · 80\n- 2026-10-03 · shop.example · delivered · 120\n- 2026-10-20 · shop.example · delivered · 45\n- 2026-10-10 · agent:courier-12 · failed · 15\n","as_of":"2026-10-22"}}}},"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body over 64 KB"}}}},"/api/v1/tier_for":{"get":{"operationId":"tierForGet","summary":"Tier for a score and an event count","description":"Turns a score (0 to 100) and the number of events behind it into a tier and what that tier allows: trusted and standard may spend up to their limit per task without asking and must ask above it, watch asks before any dealing, blocked has no dealing. A score below the watch minimum is blocked; fewer events than min_events is unrated and treated as watch; an id the person listed as blocked is blocked whatever the score. Thresholds and limits come from your arguments or the defaults. Also says how many points the next tier needs. A tier is a reading of your own record under your own rules, not a judgment of anyone.","parameters":[{"name":"score","in":"query","required":true,"description":"The score, 0 to 100, for example from score_counterparty.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"events","in":"query","required":true,"description":"How many events the score rests on.","schema":{"type":"integer","minimum":0,"maximum":100000}},{"name":"blocked","in":"query","required":false,"description":"True when the person listed this counterparty under blocked. Default false.","schema":{"type":"boolean"}},{"name":"min_events","in":"query","required":false,"description":"Events needed before a score counts. Default 3, or the file's rule.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"trusted_min","in":"query","required":false,"description":"Minimum score for the trusted tier. Default 75.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"standard_min","in":"query","required":false,"description":"Minimum score for the standard tier. Default 50.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"watch_min","in":"query","required":false,"description":"Minimum score for the watch tier; below it is blocked. Default 25.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"trusted_spend","in":"query","required":false,"description":"What a trusted counterparty may be paid per task without asking. Default 500.","schema":{"type":"number","minimum":0,"maximum":1000000000}},{"name":"standard_spend","in":"query","required":false,"description":"What a standard counterparty may be paid per task without asking. Default 100.","schema":{"type":"number","minimum":0,"maximum":1000000000}}],"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"tierFor","summary":"Tier for a score and an event count","description":"Turns a score (0 to 100) and the number of events behind it into a tier and what that tier allows: trusted and standard may spend up to their limit per task without asking and must ask above it, watch asks before any dealing, blocked has no dealing. A score below the watch minimum is blocked; fewer events than min_events is unrated and treated as watch; an id the person listed as blocked is blocked whatever the score. Thresholds and limits come from your arguments or the defaults. Also says how many points the next tier needs. A tier is a reading of your own record under your own rules, not a judgment of anyone.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"score":{"type":"number","minimum":0,"maximum":100,"description":"The score, 0 to 100, for example from score_counterparty."},"events":{"type":"integer","minimum":0,"maximum":100000,"description":"How many events the score rests on."},"blocked":{"type":"boolean","default":false,"description":"True when the person listed this counterparty under blocked. Default false."},"min_events":{"type":"integer","minimum":1,"maximum":100,"description":"Events needed before a score counts. Default 3, or the file's rule."},"trusted_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the trusted tier. Default 75."},"standard_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the standard tier. Default 50."},"watch_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the watch tier; below it is blocked. Default 25."},"trusted_spend":{"type":"number","minimum":0,"maximum":1000000000,"description":"What a trusted counterparty may be paid per task without asking. Default 500."},"standard_spend":{"type":"number","minimum":0,"maximum":1000000000,"description":"What a standard counterparty may be paid per task without asking. Default 100."}},"required":["score","events"]},"example":{"score":68,"events":5}}}},"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body over 64 KB"}}}},"/api/v1/path_to_tier":{"get":{"operationId":"pathToTierGet","summary":"Distance to a tier, and decay without new events","description":"For one counterparty (a REPUTATION.md file and an id, or its events) and a target tier: the fewest good events of one type, dated as_of, that lift the score to the tier's minimum and make it count (min_events), with the score, tier and confidence after them, and the same count for every type with a positive weight. Then, with no new events: the day the score decays to a threshold you choose (by default the nearest tier line between the score and 50), the day it comes within a band of the neutral 50, every tier line it crosses on the way, and the day the newest event turns stale. Formulas in every result. A distance on your own record, never a plan: record only events that happen.","parameters":[{"name":"counterparty","in":"query","required":false,"description":"The counterparty's id: a handle like agent:courier-12, a domain or a URL. Required with text; a label otherwise.","schema":{"type":"string"}},{"name":"text","in":"query","required":false,"description":"A whole REPUTATION.md file, as a string.","schema":{"type":"string"}},{"name":"events","in":"query","required":false,"description":"Events for one counterparty: [{ date (YYYY-MM-DD), type (delivered | honored | resolved | late | refunded | disputed | failed | breached), amount (optional, a plain number), note (optional) }]. Up to 200. URL-encoded JSON.","schema":{"type":"string"}},{"name":"target","in":"query","required":true,"description":"The tier to reach: trusted, standard, watch. Its minimum comes from the rules.","schema":{"type":"string","enum":["trusted","standard","watch"]}},{"name":"event_type","in":"query","required":false,"description":"The kind of good event to count, with a positive weight under the rules. Default delivered.","schema":{"type":"string","enum":["delivered","honored","resolved","late","refunded","disputed","failed","breached"]}},{"name":"threshold","in":"query","required":false,"description":"A score to watch the decay toward with no new events. Default: the nearest tier line between the score and 50.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"neutral_band","in":"query","required":false,"description":"How close to 50 counts as back to neutral, in points. Default 1.","schema":{"type":"number","minimum":0.1,"maximum":25}},{"name":"as_of","in":"query","required":false,"description":"The date to score as of (YYYY-MM-DD). Default: today. Ages and decay are measured from it.","schema":{"type":"string"}},{"name":"half_life_days","in":"query","required":false,"description":"An event's weight halves every this many days. Default 90, or the file's rule.","schema":{"type":"number","minimum":1,"maximum":3650}},{"name":"min_events","in":"query","required":false,"description":"Events needed before a score counts. Default 3, or the file's rule.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"review_days","in":"query","required":false,"description":"Review the whole file at least this often, in days; a score whose newest event is older is marked stale. Default 30, or the file's rule.","schema":{"type":"integer","minimum":1,"maximum":3650}},{"name":"weights","in":"query","required":false,"description":"Weight per event type, like {\"delivered\": 1, \"breached\": -3}; types you leave out keep the default or the file's rule. Defaults: delivered 1, honored 1, resolved 0.5, late -0.5, refunded -0.5, disputed -1, failed -2, breached -3. URL-encoded JSON.","schema":{"type":"string"}},{"name":"trusted_min","in":"query","required":false,"description":"Minimum score for the trusted tier. Default 75.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"standard_min","in":"query","required":false,"description":"Minimum score for the standard tier. Default 50.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"watch_min","in":"query","required":false,"description":"Minimum score for the watch tier; below it is blocked. Default 25.","schema":{"type":"number","minimum":0,"maximum":100}}],"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"pathToTier","summary":"Distance to a tier, and decay without new events","description":"For one counterparty (a REPUTATION.md file and an id, or its events) and a target tier: the fewest good events of one type, dated as_of, that lift the score to the tier's minimum and make it count (min_events), with the score, tier and confidence after them, and the same count for every type with a positive weight. Then, with no new events: the day the score decays to a threshold you choose (by default the nearest tier line between the score and 50), the day it comes within a band of the neutral 50, every tier line it crosses on the way, and the day the newest event turns stale. Formulas in every result. A distance on your own record, never a plan: record only events that happen.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"counterparty":{"type":"string","maxLength":120,"description":"The counterparty's id: a handle like agent:courier-12, a domain or a URL. Required with text; a label otherwise."},"text":{"type":"string","maxLength":200000,"description":"A whole REPUTATION.md file, as a string."},"events":{"type":"array","maxItems":200,"items":{"type":"object","properties":{"date":{"type":"string"},"type":{"type":"string","enum":["delivered","honored","resolved","late","refunded","disputed","failed","breached"]},"amount":{"type":"number"},"note":{"type":"string"}},"required":["date","type"]},"description":"Events for one counterparty: [{ date (YYYY-MM-DD), type (delivered | honored | resolved | late | refunded | disputed | failed | breached), amount (optional, a plain number), note (optional) }]. Up to 200."},"target":{"type":"string","enum":["trusted","standard","watch"],"description":"The tier to reach: trusted, standard, watch. Its minimum comes from the rules."},"event_type":{"type":"string","enum":["delivered","honored","resolved","late","refunded","disputed","failed","breached"],"description":"The kind of good event to count, with a positive weight under the rules. Default delivered."},"threshold":{"type":"number","minimum":0,"maximum":100,"description":"A score to watch the decay toward with no new events. Default: the nearest tier line between the score and 50."},"neutral_band":{"type":"number","minimum":0.1,"maximum":25,"description":"How close to 50 counts as back to neutral, in points. Default 1."},"as_of":{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The date to score as of (YYYY-MM-DD). Default: today. Ages and decay are measured from it."},"half_life_days":{"type":"number","minimum":1,"maximum":3650,"description":"An event's weight halves every this many days. Default 90, or the file's rule."},"min_events":{"type":"integer","minimum":1,"maximum":100,"description":"Events needed before a score counts. Default 3, or the file's rule."},"review_days":{"type":"integer","minimum":1,"maximum":3650,"description":"Review the whole file at least this often, in days; a score whose newest event is older is marked stale. Default 30, or the file's rule."},"weights":{"type":"object","description":"Weight per event type, like {\"delivered\": 1, \"breached\": -3}; types you leave out keep the default or the file's rule. Defaults: delivered 1, honored 1, resolved 0.5, late -0.5, refunded -0.5, disputed -1, failed -2, breached -3.","properties":{"delivered":{"type":"number","minimum":-10,"maximum":10},"honored":{"type":"number","minimum":-10,"maximum":10},"resolved":{"type":"number","minimum":-10,"maximum":10},"late":{"type":"number","minimum":-10,"maximum":10},"refunded":{"type":"number","minimum":-10,"maximum":10},"disputed":{"type":"number","minimum":-10,"maximum":10},"failed":{"type":"number","minimum":-10,"maximum":10},"breached":{"type":"number","minimum":-10,"maximum":10}}},"trusted_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the trusted tier. Default 75."},"standard_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the standard tier. Default 50."},"watch_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the watch tier; below it is blocked. Default 25."}},"required":["target"]},"example":{"counterparty":"shop.example","text":"---\nreputation: 1\nupdated: 2026-10-22\n---\n## Counterparties\n- shop.example · store · parts\n- agent:courier-12 · agent · delivery\n## Events\n- 2026-09-21 · shop.example · late · 80\n- 2026-10-03 · shop.example · delivered · 120\n- 2026-10-20 · shop.example · delivered · 45\n- 2026-10-10 · agent:courier-12 · failed · 15\n","as_of":"2026-10-22","target":"trusted","threshold":60}}}},"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body over 64 KB"}}}},"/api/v1/decay_curve":{"get":{"operationId":"decayCurveGet","summary":"How a score decays with no new events","description":"A score's path over the next days if no new event is recorded, from the score, the evidence mass behind it (score_counterparty returns evidence_mass and effective_events) and the half-life. With no new events every contribution decays by the same factor, so the score drifts toward the neutral 50 and the confidence toward 0. Returns the score and confidence at each step, the exact day the score crosses each tier minimum (falling from above or rising from below), the score at one half-life and at the end. Arithmetic on your numbers; a schedule for when to re-score, not a forecast of behavior.","parameters":[{"name":"score","in":"query","required":true,"description":"The score today, 0 to 100.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"evidence_mass","in":"query","required":true,"description":"positive_mass + negative_mass behind the score today, from score_counterparty.","schema":{"type":"number","minimum":0,"maximum":1000000}},{"name":"effective_events","in":"query","required":false,"description":"The decayed event count behind the score today, for the confidence path. Optional.","schema":{"type":"number","minimum":0,"maximum":1000000}},{"name":"days","in":"query","required":false,"description":"How many days ahead to trace. Default 180.","schema":{"type":"integer","minimum":1,"maximum":3650}},{"name":"step_days","in":"query","required":false,"description":"Days between points. Default 30.","schema":{"type":"integer","minimum":1,"maximum":365}},{"name":"half_life_days","in":"query","required":false,"description":"An event's weight halves every this many days. Default 90, or the file's rule.","schema":{"type":"number","minimum":1,"maximum":3650}},{"name":"trusted_min","in":"query","required":false,"description":"Minimum score for the trusted tier. Default 75.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"standard_min","in":"query","required":false,"description":"Minimum score for the standard tier. Default 50.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"watch_min","in":"query","required":false,"description":"Minimum score for the watch tier; below it is blocked. Default 25.","schema":{"type":"number","minimum":0,"maximum":100}}],"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"decayCurve","summary":"How a score decays with no new events","description":"A score's path over the next days if no new event is recorded, from the score, the evidence mass behind it (score_counterparty returns evidence_mass and effective_events) and the half-life. With no new events every contribution decays by the same factor, so the score drifts toward the neutral 50 and the confidence toward 0. Returns the score and confidence at each step, the exact day the score crosses each tier minimum (falling from above or rising from below), the score at one half-life and at the end. Arithmetic on your numbers; a schedule for when to re-score, not a forecast of behavior.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"score":{"type":"number","minimum":0,"maximum":100,"description":"The score today, 0 to 100."},"evidence_mass":{"type":"number","minimum":0,"maximum":1000000,"description":"positive_mass + negative_mass behind the score today, from score_counterparty."},"effective_events":{"type":"number","minimum":0,"maximum":1000000,"description":"The decayed event count behind the score today, for the confidence path. Optional."},"days":{"type":"integer","minimum":1,"maximum":3650,"default":180,"description":"How many days ahead to trace. Default 180."},"step_days":{"type":"integer","minimum":1,"maximum":365,"default":30,"description":"Days between points. Default 30."},"half_life_days":{"type":"number","minimum":1,"maximum":3650,"description":"An event's weight halves every this many days. Default 90, or the file's rule."},"trusted_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the trusted tier. Default 75."},"standard_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the standard tier. Default 50."},"watch_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the watch tier; below it is blocked. Default 25."}},"required":["score","evidence_mass"]},"example":{"score":82,"evidence_mass":6,"effective_events":7,"half_life_days":90,"days":180,"step_days":30}}}},"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body over 64 KB"}}}},"/api/v1/share_summary":{"get":{"operationId":"shareSummaryGet","summary":"Share a summary another agent can check","description":"Turns one counterparty's record (a REPUTATION.md file and an id, or its events) into a compact summary in canonical JSON: the counterparty id, as_of, score, tier, confidence, event counts by type, the newest event date and the sha256 of your rules section, with an id that is the sha256 of the canonical text. Pass the summary and the id to another agent; it sends both back here as shared and id to check that nothing changed. Notes, amounts, the owner and every other counterparty stay out. The id is a hash, not a signature (a proof record at proof.md can sign it; optional). Share only when the person you work for says so; a summary is your reading of your own record, not a rating of anyone.","parameters":[{"name":"counterparty","in":"query","required":false,"description":"The counterparty's id: a handle like agent:courier-12, a domain or a URL. Required to make a summary.","schema":{"type":"string"}},{"name":"text","in":"query","required":false,"description":"A whole REPUTATION.md file, as a string.","schema":{"type":"string"}},{"name":"events","in":"query","required":false,"description":"Events for one counterparty: [{ date (YYYY-MM-DD), type (delivered | honored | resolved | late | refunded | disputed | failed | breached), amount (optional, a plain number), note (optional) }]. Up to 200. URL-encoded JSON.","schema":{"type":"string"}},{"name":"as_of","in":"query","required":false,"description":"The date to score as of (YYYY-MM-DD). Default: today. Ages and decay are measured from it.","schema":{"type":"string"}},{"name":"half_life_days","in":"query","required":false,"description":"An event's weight halves every this many days. Default 90, or the file's rule.","schema":{"type":"number","minimum":1,"maximum":3650}},{"name":"min_events","in":"query","required":false,"description":"Events needed before a score counts. Default 3, or the file's rule.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"weights","in":"query","required":false,"description":"Weight per event type, like {\"delivered\": 1, \"breached\": -3}; types you leave out keep the default or the file's rule. Defaults: delivered 1, honored 1, resolved 0.5, late -0.5, refunded -0.5, disputed -1, failed -2, breached -3. URL-encoded JSON.","schema":{"type":"string"}},{"name":"trusted_min","in":"query","required":false,"description":"Minimum score for the trusted tier. Default 75.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"standard_min","in":"query","required":false,"description":"Minimum score for the standard tier. Default 50.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"watch_min","in":"query","required":false,"description":"Minimum score for the watch tier; below it is blocked. Default 25.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"shared","in":"query","required":false,"description":"To check a summary you received: the shared object exactly as sent. Send it with id; leave out text and events. URL-encoded JSON.","schema":{"type":"string"}},{"name":"id","in":"query","required":false,"description":"With shared: the id the sender gave you, 64 hex characters.","schema":{"type":"string"}}],"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"shareSummary","summary":"Share a summary another agent can check","description":"Turns one counterparty's record (a REPUTATION.md file and an id, or its events) into a compact summary in canonical JSON: the counterparty id, as_of, score, tier, confidence, event counts by type, the newest event date and the sha256 of your rules section, with an id that is the sha256 of the canonical text. Pass the summary and the id to another agent; it sends both back here as shared and id to check that nothing changed. Notes, amounts, the owner and every other counterparty stay out. The id is a hash, not a signature (a proof record at proof.md can sign it; optional). Share only when the person you work for says so; a summary is your reading of your own record, not a rating of anyone.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"counterparty":{"type":"string","maxLength":120,"description":"The counterparty's id: a handle like agent:courier-12, a domain or a URL. Required to make a summary."},"text":{"type":"string","maxLength":200000,"description":"A whole REPUTATION.md file, as a string."},"events":{"type":"array","maxItems":200,"items":{"type":"object","properties":{"date":{"type":"string"},"type":{"type":"string","enum":["delivered","honored","resolved","late","refunded","disputed","failed","breached"]},"amount":{"type":"number"},"note":{"type":"string"}},"required":["date","type"]},"description":"Events for one counterparty: [{ date (YYYY-MM-DD), type (delivered | honored | resolved | late | refunded | disputed | failed | breached), amount (optional, a plain number), note (optional) }]. Up to 200."},"as_of":{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The date to score as of (YYYY-MM-DD). Default: today. Ages and decay are measured from it."},"half_life_days":{"type":"number","minimum":1,"maximum":3650,"description":"An event's weight halves every this many days. Default 90, or the file's rule."},"min_events":{"type":"integer","minimum":1,"maximum":100,"description":"Events needed before a score counts. Default 3, or the file's rule."},"weights":{"type":"object","description":"Weight per event type, like {\"delivered\": 1, \"breached\": -3}; types you leave out keep the default or the file's rule. Defaults: delivered 1, honored 1, resolved 0.5, late -0.5, refunded -0.5, disputed -1, failed -2, breached -3.","properties":{"delivered":{"type":"number","minimum":-10,"maximum":10},"honored":{"type":"number","minimum":-10,"maximum":10},"resolved":{"type":"number","minimum":-10,"maximum":10},"late":{"type":"number","minimum":-10,"maximum":10},"refunded":{"type":"number","minimum":-10,"maximum":10},"disputed":{"type":"number","minimum":-10,"maximum":10},"failed":{"type":"number","minimum":-10,"maximum":10},"breached":{"type":"number","minimum":-10,"maximum":10}}},"trusted_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the trusted tier. Default 75."},"standard_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the standard tier. Default 50."},"watch_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the watch tier; below it is blocked. Default 25."},"shared":{"type":"object","description":"To check a summary you received: the shared object exactly as sent. Send it with id; leave out text and events."},"id":{"type":"string","maxLength":64,"description":"With shared: the id the sender gave you, 64 hex characters."}}},"example":{"counterparty":"shop.example","text":"---\nreputation: 1\nupdated: 2026-10-22\n---\n## Counterparties\n- shop.example · store · parts\n- agent:courier-12 · agent · delivery\n## Events\n- 2026-09-21 · shop.example · late · 80\n- 2026-10-03 · shop.example · delivered · 120\n- 2026-10-20 · shop.example · delivered · 45\n- 2026-10-10 · agent:courier-12 · failed · 15\n","as_of":"2026-10-22"}}}},"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body over 64 KB"}}}},"/api/v1/merge_records":{"get":{"operationId":"mergeRecordsGet","summary":"Merge two files into one","description":"Merges two REPUTATION.md files into a merged file you can save. Counterparties merge by id (categories joined; a differing kind or note is reported as a conflict and the preferred file's value kept); events are deduplicated by counterparty, date and type and sorted by date; the preferred file's Rules win, and the blocked lists of both are joined so no block is lost. Returns the merged file as text with the counts of what was added and dropped. Nothing is stored.","parameters":[{"name":"a","in":"query","required":true,"description":"The first REPUTATION.md file, as a string.","schema":{"type":"string"}},{"name":"b","in":"query","required":true,"description":"The second REPUTATION.md file, as a string.","schema":{"type":"string"}},{"name":"prefer","in":"query","required":false,"description":"Whose rules, owner, kinds and notes win on a conflict. Default a.","schema":{"type":"string","enum":["a","b"]}},{"name":"as_of","in":"query","required":false,"description":"The merge date, written as updated (YYYY-MM-DD). Default: today.","schema":{"type":"string"}}],"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"mergeRecords","summary":"Merge two files into one","description":"Merges two REPUTATION.md files into a merged file you can save. Counterparties merge by id (categories joined; a differing kind or note is reported as a conflict and the preferred file's value kept); events are deduplicated by counterparty, date and type and sorted by date; the preferred file's Rules win, and the blocked lists of both are joined so no block is lost. Returns the merged file as text with the counts of what was added and dropped. Nothing is stored.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"a":{"type":"string","maxLength":200000,"description":"The first REPUTATION.md file, as a string."},"b":{"type":"string","maxLength":200000,"description":"The second REPUTATION.md file, as a string."},"prefer":{"type":"string","enum":["a","b"],"default":"a","description":"Whose rules, owner, kinds and notes win on a conflict. Default a."},"as_of":{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The merge date, written as updated (YYYY-MM-DD). Default: today."}},"required":["a","b"]},"example":{"a":"---\nreputation: 1\nupdated: 2026-10-20\n---\n## Counterparties\n- shop.example · store · parts · main parts supplier\n## Events\n- 2026-10-03 · shop.example · delivered · 120\n- 2026-10-10 · shop.example · late · 45\n## Rules\n- half_life_days: 60\n","b":"---\nreputation: 1\nupdated: 2026-10-21\n---\n## Counterparties\n- shop.example · store · tools\n- agent:courier-12 · agent · delivery\n## Events\n- 2026-10-03 · shop.example · delivered · 120\n- 2026-10-19 · agent:courier-12 · delivered · 15\n## Rules\n- blocked: agent:reseller-9\n","prefer":"a","as_of":"2026-10-22"}}}},"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body over 64 KB"}}}},"/api/v1/check_reputation":{"get":{"operationId":"checkReputationGet","summary":"Check a file","description":"Lints a REPUTATION.md file sent as text: the frontmatter, every counterparty line (id, kind, categories), every event line (date, counterparty, type, amount), the Rules section (unknown or repeated keys, ranges, tier order, weight signs, ids under blocked), events for undeclared counterparties, counterparties with no events, duplicate events, events dated after as_of, notes that read like instructions, and whether the review interval has passed. Returns each finding with its line number and level, counts, the rules in force (file over defaults) and a short score and tier per counterparty. A clean result means the file is readable, not that any record in it is true.","parameters":[{"name":"text","in":"query","required":true,"description":"The whole REPUTATION.md file, as a string.","schema":{"type":"string"}},{"name":"as_of","in":"query","required":false,"description":"The date to score as of (YYYY-MM-DD). Default: today. Ages and decay are measured from it.","schema":{"type":"string"}}],"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"checkReputation","summary":"Check a file","description":"Lints a REPUTATION.md file sent as text: the frontmatter, every counterparty line (id, kind, categories), every event line (date, counterparty, type, amount), the Rules section (unknown or repeated keys, ranges, tier order, weight signs, ids under blocked), events for undeclared counterparties, counterparties with no events, duplicate events, events dated after as_of, notes that read like instructions, and whether the review interval has passed. Returns each finding with its line number and level, counts, the rules in force (file over defaults) and a short score and tier per counterparty. A clean result means the file is readable, not that any record in it is true.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","maxLength":200000,"description":"The whole REPUTATION.md file, as a string."},"as_of":{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The date to score as of (YYYY-MM-DD). Default: today. Ages and decay are measured from it."}},"required":["text"]},"example":{"text":"---\nreputation: 1\nupdated: 2026-10-22\n---\n## Counterparties\n- shop.example · store · parts\n- agent:courier-12 · agent · delivery\n## Events\n- 2026-10-03 · shop.example · delivered · 120\n- 2026-10-12 · shop.example · shipped · 45\n- 2026-10-10 · agent:courier-12 · failed · $15\n","as_of":"2026-10-22"}}}},"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body over 64 KB"}}}},"/api/v1/parse_reputation":{"get":{"operationId":"parseReputationGet","summary":"Parse a file to canonical JSON","description":"Reads a REPUTATION.md file sent as text with the same parser every tool here uses and returns it as canonical JSON: counterparties sorted by id, events sorted by date, the rules in force (the file over the defaults), which rule keys the file set, every issue with its line number, the canonical text and its sha256, so two copies with the same content give the same hash however they were written. Use it to hand the format to a program or another agent without writing a parser. It reads only the text you send; it scores nothing, fetches nothing and keeps nothing, and readable is not true: the records are your own.","parameters":[{"name":"text","in":"query","required":true,"description":"A whole REPUTATION.md file, as a string.","schema":{"type":"string"}},{"name":"as_of","in":"query","required":false,"description":"The date to score as of (YYYY-MM-DD). Default: today. Ages and decay are measured from it.","schema":{"type":"string"}}],"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"parseReputation","summary":"Parse a file to canonical JSON","description":"Reads a REPUTATION.md file sent as text with the same parser every tool here uses and returns it as canonical JSON: counterparties sorted by id, events sorted by date, the rules in force (the file over the defaults), which rule keys the file set, every issue with its line number, the canonical text and its sha256, so two copies with the same content give the same hash however they were written. Use it to hand the format to a program or another agent without writing a parser. It reads only the text you send; it scores nothing, fetches nothing and keeps nothing, and readable is not true: the records are your own.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","maxLength":200000,"description":"A whole REPUTATION.md file, as a string."},"as_of":{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The date to score as of (YYYY-MM-DD). Default: today. Ages and decay are measured from it."}},"required":["text"]},"example":{"text":"---\nreputation: 1\nupdated: 2026-10-22\n---\n## Counterparties\n- shop.example · store · parts\n- agent:courier-12 · agent · delivery\n## Events\n- 2026-09-21 · shop.example · late · 80\n- 2026-10-03 · shop.example · delivered · 120\n- 2026-10-20 · shop.example · delivered · 45\n- 2026-10-10 · agent:courier-12 · failed · 15\n","as_of":"2026-10-22"}}}},"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body over 64 KB"}}}},"/api/v1/reputation_template":{"get":{"operationId":"reputationTemplateGet","summary":"Start a file","description":"Builds a ready-to-save REPUTATION.md from a few arguments: the owner, one counterparty (id, kind, categories), its first event (type, date, amount, note) and the rules (half-life, minimum events, review interval, tier minimums and spend limits), with the defaults for anything you leave out. Returns the file as text with the next steps. Nothing is stored.","parameters":[{"name":"owner","in":"query","required":false,"description":"Who keeps the file, like agent:buyer-7. Optional.","schema":{"type":"string"}},{"name":"counterparty","in":"query","required":true,"description":"The first counterparty's id: a handle like agent:courier-12, a domain or a URL.","schema":{"type":"string"}},{"name":"kind","in":"query","required":true,"description":"What the counterparty is: agent, service, store, firm.","schema":{"type":"string","enum":["agent","service","store","firm"]}},{"name":"categories","in":"query","required":false,"description":"Comma-separated categories of dealing, like parts, tools. Optional.","schema":{"type":"string"}},{"name":"counterparty_note","in":"query","required":false,"description":"A short note on the counterparty. Optional.","schema":{"type":"string"}},{"name":"event_type","in":"query","required":false,"description":"The first event's type: delivered, honored, resolved, late, refunded, disputed, failed, breached. Default delivered.","schema":{"type":"string","enum":["delivered","honored","resolved","late","refunded","disputed","failed","breached"]}},{"name":"event_date","in":"query","required":false,"description":"The first event's date (YYYY-MM-DD). Default: as_of.","schema":{"type":"string"}},{"name":"amount","in":"query","required":false,"description":"The first event's amount, a plain number in your own unit. Optional.","schema":{"type":"number","minimum":0,"maximum":1000000000000}},{"name":"note","in":"query","required":false,"description":"A short note on the first event. Optional.","schema":{"type":"string"}},{"name":"as_of","in":"query","required":false,"description":"Written as updated (YYYY-MM-DD). Default: today.","schema":{"type":"string"}},{"name":"half_life_days","in":"query","required":false,"description":"An event's weight halves every this many days. Default 90, or the file's rule.","schema":{"type":"number","minimum":1,"maximum":3650}},{"name":"min_events","in":"query","required":false,"description":"Events needed before a score counts. Default 3, or the file's rule.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"review_days","in":"query","required":false,"description":"Review the whole file at least this often, in days; a score whose newest event is older is marked stale. Default 30, or the file's rule.","schema":{"type":"integer","minimum":1,"maximum":3650}},{"name":"trusted_min","in":"query","required":false,"description":"Minimum score for the trusted tier. Default 75.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"standard_min","in":"query","required":false,"description":"Minimum score for the standard tier. Default 50.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"watch_min","in":"query","required":false,"description":"Minimum score for the watch tier; below it is blocked. Default 25.","schema":{"type":"number","minimum":0,"maximum":100}},{"name":"trusted_spend","in":"query","required":false,"description":"What a trusted counterparty may be paid per task without asking. Default 500.","schema":{"type":"number","minimum":0,"maximum":1000000000}},{"name":"standard_spend","in":"query","required":false,"description":"What a standard counterparty may be paid per task without asking. Default 100.","schema":{"type":"number","minimum":0,"maximum":1000000000}}],"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"reputationTemplate","summary":"Start a file","description":"Builds a ready-to-save REPUTATION.md from a few arguments: the owner, one counterparty (id, kind, categories), its first event (type, date, amount, note) and the rules (half-life, minimum events, review interval, tier minimums and spend limits), with the defaults for anything you leave out. Returns the file as text with the next steps. Nothing is stored.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"owner":{"type":"string","maxLength":80,"description":"Who keeps the file, like agent:buyer-7. Optional."},"counterparty":{"type":"string","maxLength":120,"description":"The first counterparty's id: a handle like agent:courier-12, a domain or a URL."},"kind":{"type":"string","enum":["agent","service","store","firm"],"description":"What the counterparty is: agent, service, store, firm."},"categories":{"type":"string","maxLength":200,"description":"Comma-separated categories of dealing, like parts, tools. Optional."},"counterparty_note":{"type":"string","maxLength":120,"description":"A short note on the counterparty. Optional."},"event_type":{"type":"string","enum":["delivered","honored","resolved","late","refunded","disputed","failed","breached"],"default":"delivered","description":"The first event's type: delivered, honored, resolved, late, refunded, disputed, failed, breached. Default delivered."},"event_date":{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The first event's date (YYYY-MM-DD). Default: as_of."},"amount":{"type":"number","minimum":0,"maximum":1000000000000,"description":"The first event's amount, a plain number in your own unit. Optional."},"note":{"type":"string","maxLength":120,"description":"A short note on the first event. Optional."},"as_of":{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Written as updated (YYYY-MM-DD). Default: today."},"half_life_days":{"type":"number","minimum":1,"maximum":3650,"description":"An event's weight halves every this many days. Default 90, or the file's rule."},"min_events":{"type":"integer","minimum":1,"maximum":100,"description":"Events needed before a score counts. Default 3, or the file's rule."},"review_days":{"type":"integer","minimum":1,"maximum":3650,"description":"Review the whole file at least this often, in days; a score whose newest event is older is marked stale. Default 30, or the file's rule."},"trusted_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the trusted tier. Default 75."},"standard_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the standard tier. Default 50."},"watch_min":{"type":"number","minimum":0,"maximum":100,"description":"Minimum score for the watch tier; below it is blocked. Default 25."},"trusted_spend":{"type":"number","minimum":0,"maximum":1000000000,"description":"What a trusted counterparty may be paid per task without asking. Default 500."},"standard_spend":{"type":"number","minimum":0,"maximum":1000000000,"description":"What a standard counterparty may be paid per task without asking. Default 100."}},"required":["counterparty","kind"]},"example":{"owner":"agent:buyer-7","counterparty":"shop.example","kind":"store","categories":"parts, tools","event_type":"delivered","event_date":"2026-10-03","amount":120,"note":"order 441 on time","as_of":"2026-10-22"}}}},"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body over 64 KB"}}}},"/api/v1/reputation_starter":{"get":{"operationId":"reputationStarterGet","summary":"Get a starter rule set","description":"Serves four ready-to-use REPUTATION.md starters, each with rules tuned for one kind of dealing: buying from stores, hiring agent services, data and API providers, and contractors. Without kind it lists them with when to use each and its URL; with kind it returns the file, its rules and why each number was chosen, how the rules differ from the defaults, how they score the file's made-up example records, a check of the file, an empty copy with the same rules and no records, and the Rules block to paste into a file you already keep. The starters are fixed text on this site with reserved .example names and made-up numbers; the person approves the rules before use, and scores stay a reading of your own record, never a rating of anyone.","parameters":[{"name":"kind","in":"query","required":false,"description":"Which starter: buying-from-stores (frequent small orders: half-life 60 days, late and refunded cost little), hiring-agent-services (tasks delegated to other agents: half-life 45 days, 5 events before a score counts, higher tiers), data-and-api-providers (one event per period you check: half-life 30 days, 8 events to count), contractors (staged jobs: half-life 180 days, heavier weights). Leave out for the list.","schema":{"type":"string","enum":["buying-from-stores","hiring-agent-services","data-and-api-providers","contractors"]}}],"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"reputationStarter","summary":"Get a starter rule set","description":"Serves four ready-to-use REPUTATION.md starters, each with rules tuned for one kind of dealing: buying from stores, hiring agent services, data and API providers, and contractors. Without kind it lists them with when to use each and its URL; with kind it returns the file, its rules and why each number was chosen, how the rules differ from the defaults, how they score the file's made-up example records, a check of the file, an empty copy with the same rules and no records, and the Rules block to paste into a file you already keep. The starters are fixed text on this site with reserved .example names and made-up numbers; the person approves the rules before use, and scores stay a reading of your own record, never a rating of anyone.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"type":"string","enum":["buying-from-stores","hiring-agent-services","data-and-api-providers","contractors"],"description":"Which starter: buying-from-stores (frequent small orders: half-life 60 days, late and refunded cost little), hiring-agent-services (tasks delegated to other agents: half-life 45 days, 5 events before a score counts, higher tiers), data-and-api-providers (one event per period you check: half-life 30 days, 8 events to count), contractors (staged jobs: half-life 180 days, heavier weights). Leave out for the list."}}},"example":{"kind":"contractors"}}}},"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body over 64 KB"}}}},"/api/v1/build_settings":{"get":{"operationId":"buildSettingsGet","summary":"Write your settings into the skill","description":"Turns a preset and settings into the sections written at the top of REPUTATION.md. Every setting is a number or a fixed choice; the catalog is at https://reputation.md/api/v1/settings. Returns the sections as Markdown, the settings as JSON, a link to the skill with them written in and a one-line install. Out-of-range numbers are clamped with a note. Nothing is stored. Settings an agent drafted count only after the person says yes: show them to the person first, and follow them only once they agree.","parameters":[{"name":"preset","in":"query","required":false,"description":"Starting point: core, recommended, strict, forgiving. Applied first; each setting overrides it.","schema":{"type":"string","enum":["core","recommended","strict","forgiving"]}},{"name":"w_delivered","in":"query","required":false,"description":"Delivered (points). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":-10,"maximum":10}},{"name":"w_honored","in":"query","required":false,"description":"Honored (points). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":-10,"maximum":10}},{"name":"w_resolved","in":"query","required":false,"description":"Resolved (points). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":-10,"maximum":10}},{"name":"w_late","in":"query","required":false,"description":"Late (points). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":-10,"maximum":10}},{"name":"w_refunded","in":"query","required":false,"description":"Refunded (points). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":-10,"maximum":10}},{"name":"w_disputed","in":"query","required":false,"description":"Disputed (points). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":-10,"maximum":10}},{"name":"w_failed","in":"query","required":false,"description":"Failed (points). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":-10,"maximum":10}},{"name":"w_breached","in":"query","required":false,"description":"Breached (points). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":-10,"maximum":10}},{"name":"half_life_days","in":"query","required":false,"description":"Half-life (days). Default 90. Out-of-range values are clamped.","schema":{"type":"integer","minimum":7,"maximum":730}},{"name":"min_events","in":"query","required":false,"description":"Events before a score counts (events). Default 3. Out-of-range values are clamped.","schema":{"type":"integer","minimum":1,"maximum":20}},{"name":"review_days","in":"query","required":false,"description":"Review interval (days). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"integer","minimum":1,"maximum":365}},{"name":"trusted_min","in":"query","required":false,"description":"Trusted from a score of (points). Default 75. Out-of-range values are clamped.","schema":{"type":"integer","minimum":0,"maximum":100}},{"name":"standard_min","in":"query","required":false,"description":"Standard from a score of (points). Default 50. Capped at trusted_min. Out-of-range values are clamped.","schema":{"type":"integer","minimum":0,"maximum":100}},{"name":"watch_min","in":"query","required":false,"description":"Watch from a score of (blocked below) (points). Default 25. Capped at standard_min. Out-of-range values are clamped.","schema":{"type":"integer","minimum":0,"maximum":100}},{"name":"trusted_spend","in":"query","required":false,"description":"Trusted: spend without asking (per task). Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":0,"maximum":1000000}},{"name":"standard_spend","in":"query","required":false,"description":"Standard: spend without asking (per task). Capped at trusted_spend. Optional; unset clears it. Out-of-range values are clamped.","schema":{"type":"number","minimum":0,"maximum":1000000}},{"name":"format","in":"query","required":false,"description":"section (default): the settings sections only; skill: the whole skill file too.","schema":{"type":"string","enum":["section","skill"]}}],"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"buildSettings","summary":"Write your settings into the skill","description":"Turns a preset and settings into the sections written at the top of REPUTATION.md. Every setting is a number or a fixed choice; the catalog is at https://reputation.md/api/v1/settings. Returns the sections as Markdown, the settings as JSON, a link to the skill with them written in and a one-line install. Out-of-range numbers are clamped with a note. Nothing is stored. Settings an agent drafted count only after the person says yes: show them to the person first, and follow them only once they agree.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"preset":{"type":"string","enum":["core","recommended","strict","forgiving"],"description":"Starting point: core, recommended, strict, forgiving. Applied first; each setting overrides it."},"w_delivered":{"type":"number","minimum":-10,"maximum":10,"description":"Delivered (points). Optional; unset clears it. Out-of-range values are clamped."},"w_honored":{"type":"number","minimum":-10,"maximum":10,"description":"Honored (points). Optional; unset clears it. Out-of-range values are clamped."},"w_resolved":{"type":"number","minimum":-10,"maximum":10,"description":"Resolved (points). Optional; unset clears it. Out-of-range values are clamped."},"w_late":{"type":"number","minimum":-10,"maximum":10,"description":"Late (points). Optional; unset clears it. Out-of-range values are clamped."},"w_refunded":{"type":"number","minimum":-10,"maximum":10,"description":"Refunded (points). Optional; unset clears it. Out-of-range values are clamped."},"w_disputed":{"type":"number","minimum":-10,"maximum":10,"description":"Disputed (points). Optional; unset clears it. Out-of-range values are clamped."},"w_failed":{"type":"number","minimum":-10,"maximum":10,"description":"Failed (points). Optional; unset clears it. Out-of-range values are clamped."},"w_breached":{"type":"number","minimum":-10,"maximum":10,"description":"Breached (points). Optional; unset clears it. Out-of-range values are clamped."},"half_life_days":{"type":"integer","minimum":7,"maximum":730,"description":"Half-life (days). Default 90. Out-of-range values are clamped."},"min_events":{"type":"integer","minimum":1,"maximum":20,"description":"Events before a score counts (events). Default 3. Out-of-range values are clamped."},"review_days":{"type":"integer","minimum":1,"maximum":365,"description":"Review interval (days). Optional; unset clears it. Out-of-range values are clamped."},"trusted_min":{"type":"integer","minimum":0,"maximum":100,"description":"Trusted from a score of (points). Default 75. Out-of-range values are clamped."},"standard_min":{"type":"integer","minimum":0,"maximum":100,"description":"Standard from a score of (points). Default 50. Capped at trusted_min. Out-of-range values are clamped."},"watch_min":{"type":"integer","minimum":0,"maximum":100,"description":"Watch from a score of (blocked below) (points). Default 25. Capped at standard_min. Out-of-range values are clamped."},"trusted_spend":{"type":"number","minimum":0,"maximum":1000000,"description":"Trusted: spend without asking (per task). Optional; unset clears it. Out-of-range values are clamped."},"standard_spend":{"type":"number","minimum":0,"maximum":1000000,"description":"Standard: spend without asking (per task). Capped at trusted_spend. Optional; unset clears it. Out-of-range values are clamped."},"format":{"type":"string","enum":["section","skill"],"description":"section (default): the settings sections only; skill: the whole skill file too."}}},"example":{"preset":"recommended"}}}},"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body over 64 KB"}}}},"/api/v1/whats_new":{"get":{"operationId":"whatsNewGet","summary":"What's new here, and what's next","description":"What changed on reputation.md and when, what is being built, when to check back, and the other .md sites. Pass since (a date) to get only newer entries, for example the updated date of the skill you have. Reads a list kept with the code; fetches nothing and stores nothing.","parameters":[{"name":"since","in":"query","required":false,"description":"Only entries after this date (YYYY-MM-DD).","schema":{"type":"string"}},{"name":"planned","in":"query","required":false,"description":"Include what is being built and the ideas being weighed. Default true.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"whatsNew","summary":"What's new here, and what's next","description":"What changed on reputation.md and when, what is being built, when to check back, and the other .md sites. Pass since (a date) to get only newer entries, for example the updated date of the skill you have. Reads a list kept with the code; fetches nothing and stores nothing.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"since":{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Only entries after this date (YYYY-MM-DD)."},"planned":{"type":"boolean","default":true,"description":"Include what is being built and the ideas being weighed. Default true."}}},"example":{"since":"2026-10-01"}}}},"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"Bad input, with a hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body over 64 KB"}}}}},"components":{"schemas":{"Result":{"type":"object","additionalProperties":true,"properties":{"tool":{"type":"string"},"summary":{"type":"string"},"disclaimer":{"type":"string"},"terms":{"type":"string"}},"required":["disclaimer","terms"]},"Problem":{"type":"object","properties":{"error":{"type":"string"},"hint":{"type":"string"},"docs":{"type":"string"},"disclaimer":{"type":"string"},"terms":{"type":"string"}},"required":["error","disclaimer","terms"]}}}}