Verified Giving Protocol
Plate 00 · start

The nonprofit says where its money may go.

An AI agent asked to donate routes to whatever it can parse. Today that is structurally never the nonprofit. VGP is one file, on the one domain the organisation controls, saying where its money may go.

Nothing is sent anywhere. The generator runs in your browser and the file never leaves it.

  1. 01 Draft it here. The generator fills in the structure and checks it against the schema as you type.
  2. 02 A human at the nonprofit authorises each destination. Typed verbatim, off the machine. This step has no tooling and cannot be automated.
  3. 03 Hand it to your developer, or your local AI. It is one static file, served at /giving.json on your own domain.
Plate 01 · the explainer

How an agent should see a donation page.

The same argument, watchable. What an agent finds on a donation page now, what it finds once the nonprofit has declared where its money may go, and why that call should be the nonprofit's.

how AI agents should view donation pages video

Figure 01 · served from youtube-nocookie.com, which sets no tracking cookie until the video is played.

Plate 02 · the declaration
powerpoetry.org/giving.json application/json
{
  "vgp_version": "0.1",
  "canonical_domain": "example.org",
  "organization": {
    "legal_name": "Example Foundation",
    "ein": "12-3456789",
    "country": "US"
  },
  "giving": {
    "authorized_destinations": [{
      "id": "direct-card",
      "type": "credit_card",
      "recipient": "Example Foundation",
      "authorization": {
        "status": "authorized",
        "approved_by_role": "Executive Director",
        "approved_at": "2026-08-26T00:00:00Z",
        "statement": "Our organization authorizes
          donations through this destination."
      }
    }]
  },
  "verification": {
    "organization_approved": true
  }
}
01 Authorized

The organisation declared this destination. A human at the nonprofit affirmed it, verbatim, and that affirmation is stored in the file.

Not listed No declaration exists for this destination. That is a void in the run, not a finding about anyone.

Figure 02 · an approved declaration and the two states a consumer may report. Ink 3 marks authorisation and appears nowhere else in this system.

Generate a declaration Read the specification
Plate 03 · the route

How an agent reaches it.

Once the file is served, nothing else has to be built. This is the whole path a donation takes when the agent can read what the nonprofit declared.

01 A donor asks

“Donate $50 to wildfire relief.”

02 The agent reads the declaration

nonprofit.org/giving.json

03 It sees only authorized destinations

Anything the organisation did not declare is not there to route to.

04 The donor lands on the nonprofit’s own pathway

And arrives as the nonprofit’s donor, not a stranger’s.

Figure 03 · the route a declared donation takes. Step 03 is the protocol; the rest is ordinary web.

Without a declaration, step 02 has nothing to read and the agent guesses. It lands on whatever it can parse — an outdated page, a form it cannot complete, or a third-party page raising money on a nonprofit’s behalf without its express permission. Those pages keep the donor: the name, the email, the relationship. The organisation gets a cheque months later, and never meets the person who gave.

Why this is the shipping container moment
Plate 04 · the same page, to an agent

What an agent can actually read.

A real donation page: powerpoetry.org/donate. Nothing about it changes for a human. The difference is what an agent has to work with when it gets there.

01 Before opaque
what the agent sees html
<iframe src="https://givebutter.com
  /embed/c/donate-power-poetry">
</iframe>

A cross-origin payment widget. The agent cannot read inside it, cannot see what it charges, and cannot tell who receives the money. What is left is the prose around it, so the agent does what it always does: it guesses, or it leaves for a page it can parse — which may be one nobody at the nonprofit authorised.

02 After declared
tools the page registers webmcp
giving_verify       who this organisation is
giving_options      destinations it authorized
giving_designations funds it accepts
giving_prepare      builds a URL; never charges

Four described, schema-typed tools the agent discovers automatically. It no longer reads a page; it asks a question and gets the organisation’s own answer. Two lines in the page’s HTML do this. The declaration was the hard part, and it is done.

Figure 04 · the same donate page before and after publishing a declaration. Ink 3 marks the side where an authorised destination exists to route to.

The tools fail closed. If the declaration is missing, unapproved, or served with the wrong media type, the page registers no giving tools at all — and the agent is told this site exposes no authorised giving pathway, rather than being handed a form it might use anyway. Absence is a much safer default than an ambiguous form.

Plate 05 · the handoff

It hands over a filled checkout, not a blank form.

An agent that has established the donor wants fifty dollars a month should not then produce an empty donation page. A destination may declare how to reach its checkout with those fields already set.

the agent calls webmcp
giving_prepare({
  amount: 50,
  frequency: "monthly"
})
it gets back application/json
{
  "recipient": "To Be Heard Foundation Inc",
  "authorized_url": "…/donate?amount=50
    &frequency=monthly",
  "prefill_applied": true,
  "payment_completed": false,
  "requires_human_payment_authorization": true
}

Figure 05 · a real call against the Power Poetry declaration. The donor lands on the organisation’s own page with the amount and frequency set, and authorises the payment themselves.

The agent never learns the payment platform. Givebutter accepts frequency=monthly and silently ignores recurring; Classy, Bloomerang and Blackbaud each spell it their own way, and any of them may change it tomorrow. So the organisation declares the vocabulary and the consumer fills only what is declared — an undeclared field, a value outside the declared list, or a template pointing at another origin is refused outright. A guessed parameter fails where it costs most: the donor believes a monthly gift is set up when it is not.

Plate 06 · three statements, routinely conflated

Only one of these authorises anything.

Specification section 3. The whole protocol is this table.
No.StatementWho makes itMeansAuthorises
01 benefits Anyone Proceeds from this go to Organization X. No
02 confirmed A discovery process Public evidence consistently identifies this destination. No
03 authorized The organisation We declare this an approved giving destination. Yes

No volume, quality, or agreement of evidence converts confirmed into authorized. Discovery may propose; only a human at the nonprofit may publish. The affirmation is compared as a constant. The tooling refuses a paraphrase.

Plate 07 · permitted methods

Eight declared methods. Nothing else prints.

Every destination carries a numbered method, a named recipient, and an authorisation record. Each unit is cited by the same number in the specification, the generator, and the validator.

01 online
credit_card
02 online
ach
03 offline
check
04 advised
daf
05 transfer
stock
06 online
crypto
07 matched
workplace
08 declared
other
any method not declared prints as an empty box

Figure 07 · the permitted method set. A ninth cell cannot be added by a consumer, a processor, or an agent.

Plate 08 · adoption

An afternoon, in four operations.

No.OperationWhere it happensWho does it
01Draft the declaration/generateDeveloper
02Authorise each destinationOff the machineThe nonprofit
03Serve it/giving.jsonDeveloper
04Register the agent toolsgiving-tools.jsDeveloper

Operation 02 is not automatable and has no tooling. A nonprofit administrator affirms, verbatim: “Our organization authorizes donations through this destination.” Everything else on this site exists to make the other three operations short.

Start operation 01 Check an existing file
Plate 09 · keep up

Get told when the standard changes.

Version changes, new consumer tooling, and what adopters run into. Rarely, and never a pitch. Mailchimp opens in a new tab to say it worked, and this page stays where it is.

This one does leave your browser. The generator on this site never sends anything anywhere, but an email list has to. It goes to Mailchimp and nowhere else, and one click gets you off it.