Inspiration

Small merchants lose about $128 per chargeback. They win 54% of the disputes they fight, but they fight only 8%, because gathering evidence by hand takes too long. AI shopping agents add a new problem: a buyer can say "I never authorized that" when their own agent placed the order. We wanted a tool that fights the disputes worth fighting and can prove what the agent was told to buy.

What it does

Countersign is a chargeback agent for PayPal merchants. When a dispute arrives, it:

  1. Verifies the PayPal webhook and turns it into exactly one case.
  2. Gathers evidence, including a signed mandate showing what the user told their AI agent to buy.
  3. Scores the odds of winning and decides whether fighting is worth it.
  4. Drafts a response in which every claim cites stored evidence.
  5. Files the response through the PayPal Disputes API once the merchant approves it.

How we built it

  • Gateway (Go): checks each webhook's signature with PayPal's verify API, then publishes it to Redpanda. Bad events go to a dead-letter queue.
  • Mandate ledger: Ed25519-signed records chained by hash, so editing any record breaks the chain.
  • AI service (Python): a logistic regression trained on published win rates: $$P(\text{win}) = \sigma\left(\beta_0 + \textstyle\sum_i \beta_i x_i\right)$$ It fights only when $$P(\text{win}) \cdot A - c_{\text{fight}} > c_{\text{refund}}$$ where $A$ is the disputed amount.
  • Drafting: a template drafter by default, with an optional Groq LLM drafter. A grounding guard rejects any factual sentence that doesn't cite evidence.
  • Console (Next.js): sign-in, a deadline board, and the evidence, score and draft with edit and approve.
  • Deployed on Render as a Blueprint and connected to the PayPal sandbox.

Challenges

  • Sandbox webhooks: PayPal's sandbox didn't send an event for a dispute we opened from the buyer side, so we built a script that injects disputes for demos.
  • Webhook IDs: moving from a local tunnel to Render gave us a new webhook ID, and signature checks failed until the gateway's ID matched the new one.
  • LLM hallucination: better prose meant nothing if it invented facts. That's why the guard runs before the merchant ever sees a draft.
  • Honesty: order data is staged and labeled demo: true, and the win/lost ruling is simulated because sandbox rulings take days.

What we learned

  • Deciding when not to fight matters as much as winning.
  • Signed, hash-chained records are a cheap way to make evidence tamper-evident.
  • With LLMs, the guardrails do more work than the prompt.
  • Labeling what's simulated builds more trust than a polished demo that hides it.

The challenges are the ones we actually hit this session. The scoring and drafting details come from the README, so update anything the submission should describe differently.

Built With

Share this project:

Updates

Submission history