Core Concepts
Guest requests#
A donor on a public page has no login and almost no permissions. When they ask for something that needs real access — naming their guests, requesting a refund — the ask is written down first and carried out afterwards, by something that is allowed to.
Why a queue at all#
A visitor on the donor portal is not a Salesforce user. They are the site's Guest User, and the Guest User's licence permanently forbids editing or deleting records — not by configuration you could relax, but as a platform rule. So a donor who wants to write their guests' names onto their own seats is asking for something the page they are standing on cannot do.
The obvious workaround is to let the page act with borrowed privileges. That is the wrong shape: it puts a path that can write to any record behind a form that anyone on the internet can submit.
Instead the ask itself becomes a record. The visitor's request is stored as a Guest Request, returned to them immediately as a status, and applied later by a handler running under privileged access. The public page never gains a permission. The privileged code never takes instructions from a stranger about which record to touch.
What one looks like#
Every request lands in the Guest Requests tab, whatever kind it is.
| Field | What it holds |
|---|---|
| Request Type | Which kind of ask this is — the only thing that decides how it is processed. |
| Subject | The gift or ticket order the request is about. |
| Summary | A one-line human description, so the tab is readable without opening rows. |
| Status | Where the request has reached. See below. |
| Payload | The donor's own submission, as JSON. Treated as hostile input throughout. |
| Message to the donor | The sentence shown on the portal when something was refused. |
| Admin note | The internal counterpart — detail for your team, never shown to the donor. |
| Attempts | How many times processing has been tried. |
| Processed | When it reached a final state. |
The Subject field is the authorization decision, written down
When a donor submits, the controller resolves their magic-link token to a donor, finds the gift or order among that donor's own records, and stamps the id it found on the request. The visitor never names a target. Handlers are required to act only on this field — reading a record id out of the payload instead would be an insecure direct object reference with an asynchronous delay bolted on.
This is also why Subject is plain text rather than a lookup: one queue serves request types whose subjects are different objects. The cost is that requests do not appear as a related list on the record they concern — the Guest Requests tab and the Campaign related list are where you find them.
The statuses#
| Status | What it means |
|---|---|
| Pending | Written and returned to the donor. Nothing has been applied yet. |
| Processing | Claimed, and being worked on right now. A row is only ever here inside a single running transaction — if that transaction dies, the claim dies with it and the row goes back to Pending for the sweep to find. |
| Completed | Applied successfully. The seats were named; the refund was issued. |
| Awaiting Review | Accepted, checked, and deliberately parked for a person. Not a failure state — it is the normal resting place for anything the package refuses to automate. |
| Declined | Refused for a stated reason. The donor is shown that reason on the portal. |
| Failed | Something unexpected broke. Retried up to three times, then left for your team. |
How a request gets processed#
Two paths run the same code, for two different reasons.
The fast path is a queued job fired the moment the request is written. It exists because the donor is watching: someone who names four guests wants to refresh and see four names, not a promise.
The reliable path is a sweep that runs every twenty minutes and collects anything still unprocessed after a five-minute grace period. It is not a fallback bolted on for tidiness — it is what makes the guarantee real. The fast path can simply never run: the transaction may roll back, or the org may already have spent its queueable allowance. When that happens the row is still sitting there marked Pending, and the sweep finds it.
Nothing in the fast path retries, because the sweep already is the retry.
A handler that fails is retried up to three times and then stops, so a request that can never succeed does not circle forever. Requests are also written to be safe to run twice — a rollback can send the same row back through processing, and applying it again must not double anything.
The two kinds of request#
Naming your guests#
A buyer who skipped the guest-details step at checkout has seats with nobody's name on them. From the donor portal they can come back and fill those names — and email addresses — in.
Only blank seats are offered. A name captured at checkout is never overwritten by a later submission, because the person filling this in months afterwards is not necessarily the person who knows better.
See Events & ticketing for how seats are created in the first place.
Asking for a refund#
A donor can ask for a gift back from their portal, if you have turned on Let donors request a refund in Settings → Payments → Refunds. It is off until you switch it on, so no existing organization starts inviting refund requests it never asked for.
Nothing is ever refunded automatically. The request is screened, then parked at Awaiting Review
for a person. A refund is issued by a member of your team from the donation record, gated by the
same Process_Refunds permission as always.
Screening happens twice — once at the click, so an ineligible donor is told immediately rather than by email minutes later, and again at processing, because the world moves in between. A gift is turned down if refunds are switched off, if it is already fully refunded, if it is outside your refund window, if it has no card payment on file, or if it is an event ticket. Ticket refunds are arranged by phone deliberately: giving a seat back is a conversation about the event, not a payment adjustment.
When a request is accepted, two emails go out — an acknowledgement to the donor confirming the ask arrived and promising nothing, and an alert to the gift's owner and your reply-to address. Both are best-effort. The queued row is the record of the ask, and it reaches your team's tab whether or not either message sends.
See Process a refund for the reviewer's side.
What happens to old requests#
Processed requests are purged on the same retention job as application logs and abandoned donation staging rows, on the schedule set in Settings → Data retention. The queue is a work surface, not an archive — the donation record and its refund fields are the permanent record of what actually happened.
Related#
-
The donor portal
Everything a donor can do for themselves, and what each action changes.
-
Process a refund
Reviewing a donor's request, and issuing or turning down the refund.
-
Events & ticketing
Tiers, seats, and where unnamed guests come from.