{"lexicon":1,"id":"money.atmosphere.event.receive","defs":{"eventType":{"type":"string","knownValues":["app.webhook.test","payment.completed","payment.failed","payment.refunded","payment.refund_updated","payment.disputed","payment.dispute_closed","subscription.invoice_paid","subscription.updated","subscription.cancelled","subscription.payment_failed","subscription.recovered","payer.record.requested","payer.claimed","creator.proof.requested","attestation.updated","product.updated","product.archived","product.deleted","ticket.hold.created","ticket.hold.expired","tickets.issued","ticket.voided","ticket.refunded","ticket.checked_in","ticket.form_submitted","ticket.waitlist.joined","ticket.waitlist.offered","ticket.collaboration.invited","ticket.collaboration.accepted","ticket.collaboration.revoked","customer.segment.message_requested","recipient.authorization.updated"],"maxLength":64,"description":"ATM app event type."},"payment":{"type":"object","description":"Payment summary fields that form the published protocol contract. The signed HTTP webhook additionally carries private fulfillment fields not listed here (such as customerEmail, customerName, and shipping) so apps can fulfill orders; those private fields are delivered over the webhook only and are never written to public PDS records.","required":["id"],"properties":{"id":{"type":"string","maxLength":256},"paymentType":{"type":"string","maxLength":64},"amountCents":{"type":"integer"},"currency":{"type":"string","minLength":3,"maxLength":3},"status":{"type":"string","maxLength":64},"payerDid":{"type":"string","format":"did"},"recipientDid":{"type":"string","format":"did"},"metadata":{"type":"unknown","description":"Sanitized app-private display context. ATM never copies raw private buyer data into public protocol records."},"listing":{"type":"ref","ref":"com.atproto.repo.strongRef"},"entitlements":{"type":"array","items":{"type":"ref","ref":"com.atproto.repo.strongRef"}}}},"invoice":{"type":"object","required":["id"],"properties":{"id":{"type":"string","maxLength":256},"subscriptionId":{"type":"string","maxLength":256,"description":"Durable ATM subscriptions.id this invoice belongs to. Not the processor sub id."},"processorSubscriptionId":{"type":"string","maxLength":256,"description":"Processor subscription object id (e.g. Stripe sub_...)."},"amountCents":{"type":"integer"},"currency":{"type":"string","minLength":3,"maxLength":3},"firstInvoice":{"type":"boolean"}}},"subscription":{"type":"object","required":["id"],"properties":{"id":{"type":"string","maxLength":256,"description":"Durable ATM subscriptions.id. The id apps look the subscription up by."},"status":{"type":"string","maxLength":64},"processorSubscriptionId":{"type":"string","maxLength":256,"description":"Processor subscription object id (e.g. Stripe sub_...)."},"metadata":{"type":"unknown","description":"Sanitized app-private display context. Raw processor/customer data stays private to ATM."}}},"actorSummary":{"type":"object","required":["actor"],"properties":{"actor":{"type":"string","maxLength":256},"did":{"type":"string","format":"did"}}},"ticketHold":{"type":"object","required":["id"],"properties":{"id":{"type":"string","maxLength":300},"eventId":{"type":"string","maxLength":300},"paymentId":{"type":"string","maxLength":300},"status":{"type":"string","maxLength":64},"reason":{"type":"string","maxLength":512},"amountCents":{"type":"integer","minimum":0},"currency":{"type":"string","minLength":3,"maxLength":3},"quantityTotal":{"type":"integer","minimum":0},"items":{"type":"array","items":{"type":"ref","ref":"#ticketHoldItem"}}}},"ticketHoldItem":{"type":"object","required":["tierId"],"properties":{"tierId":{"type":"string","maxLength":300},"title":{"type":"string","maxLength":300},"quantity":{"type":"integer"},"unitAmount":{"type":"integer"},"unitAmountCents":{"type":"integer"},"currency":{"type":"string","minLength":3,"maxLength":3}}},"issuedTicket":{"type":"object","required":["id"],"properties":{"id":{"type":"string","maxLength":300},"eventId":{"type":"string","maxLength":300},"tierId":{"type":"string","maxLength":300},"paymentId":{"type":"string","maxLength":300},"claimId":{"type":"string","maxLength":300},"environment":{"type":"string","knownValues":["test","live"],"maxLength":16},"ownerDid":{"type":"string","format":"did"},"status":{"type":"string","maxLength":64},"ticketNumber":{"type":"string","maxLength":300},"scanToken":{"type":"string","maxLength":4000},"scanUrl":{"type":"string","format":"uri","maxLength":2000},"createdAt":{"type":"string","format":"datetime"},"updatedAt":{"type":"string","format":"datetime"}}},"ticketIssuanceSummary":{"type":"object","required":["holdId","count"],"properties":{"holdId":{"type":"string","maxLength":300},"count":{"type":"integer","minimum":0},"alreadyIssued":{"type":"boolean"}}},"ticketCheckIn":{"type":"object","required":["id","checkedInAt"],"properties":{"id":{"type":"string","maxLength":300},"checkInListId":{"type":"string","maxLength":300},"scannerDid":{"type":"string","format":"did"},"checkedInAt":{"type":"string","format":"datetime"}}},"product":{"type":"object","required":["uri"],"properties":{"uri":{"type":"string","format":"at-uri","maxLength":1024},"cid":{"type":"string","format":"cid"}}},"appProductRef":{"type":"object","properties":{"type":{"type":"string","maxLength":32},"id":{"type":"string","maxLength":512},"uri":{"type":"string","format":"at-uri","maxLength":1024},"cid":{"type":"string","format":"cid"}}},"productAppLink":{"type":"object","required":["productUri","appDid"],"properties":{"productUri":{"type":"string","format":"at-uri","maxLength":1024},"appDid":{"type":"string","format":"did"},"appProductRef":{"type":"ref","ref":"#appProductRef"},"fulfillmentUrl":{"type":"string","format":"uri","maxLength":1024},"label":{"type":"string","maxLength":800},"url":{"type":"string","format":"uri","maxLength":1024},"iconUrl":{"type":"string","format":"uri","maxLength":1024},"role":{"type":"string","maxLength":32},"status":{"type":"string","maxLength":32}}},"attestation":{"type":"object","properties":{"cid":{"type":"string","format":"cid"},"policy":{"type":"object","properties":{"appRecord":{"type":"string","knownValues":["public","private"]},"attestation":{"type":"string","knownValues":["public","private"]}}},"disabledReason":{"type":"string","maxLength":256}}},"distribution":{"type":"object","required":["planned"],"properties":{"planned":{"type":"integer","minimum":0}}},"appWebhookTest":{"type":"object","properties":{"message":{"type":"string","maxLength":512}}},"paymentCompleted":{"type":"object","required":["payment"],"properties":{"payment":{"type":"ref","ref":"#payment"},"distribution":{"type":"ref","ref":"#distribution"},"tickets":{"type":"ref","ref":"#ticketIssuanceSummary"},"attestation":{"type":"ref","ref":"#attestation"}}},"paymentFailed":{"type":"object","required":["payment"],"properties":{"payment":{"type":"ref","ref":"#payment"},"reason":{"type":"string","maxLength":512}}},"paymentRefunded":{"type":"object","required":["payment"],"properties":{"payment":{"type":"ref","ref":"#payment"},"amount":{"type":"integer","minimum":0},"amountRefundedTotalCents":{"type":"integer","minimum":0,"description":"Cumulative refunded amount for the payment in the smallest currency unit."},"partial":{"type":"boolean","description":"True when the payment is only partially refunded so far."},"reason":{"type":"string","maxLength":512},"distribution":{"type":"ref","ref":"#distribution"}}},"paymentRefundUpdated":{"type":"object","description":"A refund on the payment changed state after creation (e.g. an async refund settled, failed, or was canceled).","required":["payment","refundId","status","amountCents","amountRefundedTotalCents","partial","applicationFeeRefunded"],"properties":{"payment":{"type":"ref","ref":"#payment"},"refundId":{"type":"string","maxLength":256},"status":{"type":"string","knownValues":["pending","succeeded","failed","canceled","requires_action"],"maxLength":64},"amountCents":{"type":"integer","minimum":0,"description":"Amount of this refund in the smallest currency unit."},"amountRefundedTotalCents":{"type":"integer","minimum":0,"description":"Cumulative refunded amount for the payment in the smallest currency unit."},"partial":{"type":"boolean","description":"True when the payment is only partially refunded so far."},"applicationFeeRefunded":{"type":"boolean","description":"True when the application fee was refunded alongside this refund."},"reason":{"type":"string","maxLength":512}}},"paymentDisputed":{"type":"object","required":["payment"],"properties":{"payment":{"type":"ref","ref":"#payment"},"reason":{"type":"string","maxLength":512},"disputeReason":{"type":"string","maxLength":512},"status":{"type":"string","maxLength":64},"distribution":{"type":"ref","ref":"#distribution"}}},"paymentDisputeClosed":{"type":"object","description":"A dispute on the payment was resolved.","required":["payment","disputeId","outcome","status"],"properties":{"payment":{"type":"ref","ref":"#payment"},"disputeId":{"type":"string","maxLength":256},"outcome":{"type":"string","knownValues":["won","lost","warning_closed"],"maxLength":32},"status":{"type":"string","maxLength":64},"distributionsReinstated":{"type":"boolean","description":"True when app-share distributions reversed at dispute creation were reinstated after a won dispute."}}},"subscriptionInvoicePaid":{"type":"object","required":["payment","invoice"],"properties":{"payment":{"type":"ref","ref":"#payment"},"invoice":{"type":"ref","ref":"#invoice"},"invoiceId":{"type":"string","maxLength":256},"distribution":{"type":"ref","ref":"#distribution"},"attestation":{"type":"ref","ref":"#attestation"}}},"subscriptionUpdated":{"type":"object","required":["subscription","payment","priorAmountCents","amountCents","currency","updatedAt"],"properties":{"subscription":{"type":"ref","ref":"#subscription"},"payment":{"type":"ref","ref":"#payment"},"previousPayment":{"type":"ref","ref":"#payment"},"processorSubscriptionId":{"type":"string","maxLength":256,"description":"Processor subscription object id (e.g. Stripe sub_...). The durable join key is subscription.id."},"priorAmountCents":{"type":"integer","minimum":0},"amountCents":{"type":"integer","minimum":0},"currency":{"type":"string","minLength":3,"maxLength":3},"updatedAt":{"type":"string","format":"datetime"},"currentPeriodEnd":{"type":"string","format":"datetime"},"updatedBy":{"type":"ref","ref":"#actorSummary"},"attestation":{"type":"ref","ref":"#attestation"}}},"subscriptionCancelled":{"type":"object","required":["subscription","payment","cancelledAt"],"properties":{"subscription":{"type":"ref","ref":"#subscription"},"payment":{"type":"ref","ref":"#payment"},"processorSubscriptionId":{"type":"string","maxLength":256,"description":"Processor subscription object id (e.g. Stripe sub_...). The durable join key is subscription.id."},"cancelledAt":{"type":"string","format":"datetime"},"cancelledBy":{"type":"ref","ref":"#actorSummary"},"reason":{"type":"string","maxLength":512}}},"subscriptionPaymentFailed":{"type":"object","description":"A recurring renewal invoice failed to collect (card declined/expired, or needs SCA/3DS re-authentication — reason: authentication_required); the subscription is now past due. Charge/invoice-scoped — the subscription is NOT cancelled by a single failed cycle.","required":["subscription","payment","failedAt"],"properties":{"subscription":{"type":"ref","ref":"#subscription"},"payment":{"type":"ref","ref":"#payment"},"processorSubscriptionId":{"type":"string","maxLength":256,"description":"Processor subscription object id (e.g. Stripe sub_...). The durable join key is subscription.id."},"invoiceId":{"type":"string","maxLength":256},"reason":{"type":"string","maxLength":512},"hostedInvoiceUrl":{"type":"string","format":"uri","maxLength":2000,"description":"Hosted Stripe invoice URL for the SCA/authentication_required case, so apps can link the buyer to complete 3DS re-authentication."},"failedAt":{"type":"string","format":"datetime"}}},"subscriptionRecovered":{"type":"object","description":"A past-due subscription recovered — a renewal retry succeeded or Stripe reported the subscription active again. Apps should re-enable entitlements.","required":["subscription","payment","recoveredAt"],"properties":{"subscription":{"type":"ref","ref":"#subscription"},"payment":{"type":"ref","ref":"#payment"},"processorSubscriptionId":{"type":"string","maxLength":256,"description":"Processor subscription object id (e.g. Stripe sub_...). The durable join key is subscription.id."},"invoiceId":{"type":"string","maxLength":256},"recoveredAt":{"type":"string","format":"datetime"}}},"payerRecordRequested":{"type":"object","required":["paymentId","payerDid","recipientDid","collection","canonicalRecord","expectedCid","expiresAt"],"properties":{"paymentId":{"type":"string","maxLength":256},"payerDid":{"type":"string","format":"did"},"recipientDid":{"type":"string","format":"did"},"collection":{"type":"string","format":"nsid"},"canonicalRecord":{"type":"union","refs":["network.attested.payment.oneTime","network.attested.payment.recurring","network.attested.payment.scheduled"]},"expectedCid":{"type":"string","format":"cid"},"expiresAt":{"type":"string","format":"datetime"}}},"creatorProofRequested":{"type":"object","required":["paymentId","creatorDid","attestationCid","proofRecord","expiresAt"],"properties":{"paymentId":{"type":"string","maxLength":256},"creatorDid":{"type":"string","format":"did"},"attestationCid":{"type":"string","format":"cid"},"payerProofRef":{"type":"ref","ref":"com.atproto.repo.strongRef"},"proofRecord":{"type":"ref","ref":"network.attested.payment.proof"},"expiresAt":{"type":"string","format":"datetime"}}},"payerClaimed":{"type":"object","description":"A previously guest payer linked their DID to existing payments. Fired per originator app for the payments that app originated.","required":["did","paymentIds","claimedAt"],"properties":{"did":{"type":"string","format":"did"},"paymentIds":{"type":"array","maxLength":200,"items":{"type":"string","maxLength":256}},"subscriptionIds":{"type":"array","maxLength":200,"items":{"type":"string","maxLength":256}},"ticketIds":{"type":"array","maxLength":500,"items":{"type":"string","maxLength":300}},"claimedAt":{"type":"string","format":"datetime"}}},"attestationUpdated":{"type":"object","required":["paymentId"],"properties":{"paymentId":{"type":"string","maxLength":256}}},"productUpdated":{"type":"object","required":["product"],"properties":{"product":{"type":"ref","ref":"#product"},"creatorDid":{"type":"string","format":"did"},"appLink":{"type":"ref","ref":"#productAppLink"}}},"productArchived":{"type":"object","required":["product"],"properties":{"product":{"type":"ref","ref":"#product"},"creatorDid":{"type":"string","format":"did"},"appLink":{"type":"ref","ref":"#productAppLink"}}},"productDeleted":{"type":"object","required":["product"],"properties":{"product":{"type":"ref","ref":"#product"},"creatorDid":{"type":"string","format":"did"},"appLink":{"type":"ref","ref":"#productAppLink"}}},"ticketHoldCreated":{"type":"object","required":["hold"],"properties":{"hold":{"type":"ref","ref":"#ticketHold"}}},"ticketHoldExpired":{"type":"object","required":["hold"],"properties":{"hold":{"type":"ref","ref":"#ticketHold"}}},"ticketsIssued":{"type":"object","required":["hold","tickets"],"properties":{"paymentId":{"type":"string","maxLength":300},"claimId":{"type":"string","maxLength":300},"hold":{"type":"ref","ref":"#ticketHold"},"tickets":{"type":"array","items":{"type":"ref","ref":"#issuedTicket"}}}},"ticketVoided":{"type":"object","required":["paymentId","tickets"],"properties":{"paymentId":{"type":"string","maxLength":300},"reason":{"type":"string","maxLength":512},"tickets":{"type":"array","items":{"type":"ref","ref":"#issuedTicket"}}}},"ticketRefunded":{"type":"object","required":["paymentId","tickets"],"properties":{"paymentId":{"type":"string","maxLength":300},"reason":{"type":"string","maxLength":512},"tickets":{"type":"array","items":{"type":"ref","ref":"#issuedTicket"}}}},"ticketCheckedIn":{"type":"object","required":["ticket","checkIn"],"properties":{"ticket":{"type":"ref","ref":"#issuedTicket"},"checkIn":{"type":"ref","ref":"#ticketCheckIn"}}},"ticketFormSubmitted":{"type":"object","description":"An attendee filled the per-tier form through the anonymous ticket page. Carries the answered field KEYS only — never the answer values, which are private. Apps fetch values via tickets.atmosphere.listTicketFormResponses if entitled.","required":["ticket","tierId","submittedAt","answeredFieldKeys"],"properties":{"ticket":{"type":"ref","ref":"#issuedTicket"},"tierId":{"type":"string","maxLength":300},"submittedAt":{"type":"string","format":"datetime"},"answeredFieldKeys":{"type":"array","maxLength":30,"items":{"type":"string","maxLength":64},"description":"Keys of the fields the attendee answered. Values are NOT included; they are private DB state."}}},"ticketWaitlistJoined":{"type":"object","description":"A buyer joined the waitlist for a sold-out capacity group. Carries only ids + requested quantity; no buyer email/DID/PII.","required":["waitlist"],"properties":{"waitlist":{"type":"object","required":["id","eventId","capacityGroupId","quantity"],"properties":{"id":{"type":"string","maxLength":300},"eventId":{"type":"string","maxLength":300},"capacityGroupId":{"type":"string","maxLength":300},"tierId":{"type":"string","maxLength":300},"quantity":{"type":"integer","minimum":1}}}}},"ticketWaitlistOffered":{"type":"object","description":"Capacity reopened and ATM auto-OFFERed a held seat to the next FIFO waitlister. ATM NEVER auto-charges; the app emails the buyer to claim before offerExpiresAt. Carries the offer hold id + expiry + redacted offer info; no buyer email/PII.","required":["waitlist"],"properties":{"waitlist":{"type":"object","required":["id","eventId","capacityGroupId","quantity","offerHoldId","offerExpiresAt"],"properties":{"id":{"type":"string","maxLength":300},"eventId":{"type":"string","maxLength":300},"capacityGroupId":{"type":"string","maxLength":300},"tierId":{"type":"string","maxLength":300},"quantity":{"type":"integer","minimum":1},"offerHoldId":{"type":"string","maxLength":300},"offerExpiresAt":{"type":"string","format":"datetime"}}}}},"ticketCollaborationInvited":{"type":"object","description":"The primary organizer invited a co-organizer to operationally co-run an event (organizer-collab Part A). revenueShareBps (if present) is a recorded MANUAL-RECONCILIATION intent — ATM never auto-splits or auto-pays ticket revenue. No PII beyond DIDs.","required":["collaboration"],"properties":{"collaboration":{"type":"ref","ref":"#ticketCollaboration"}}},"ticketCollaborationAccepted":{"type":"object","description":"The co-organizer accepted their invitation (dual-consent). They now have operational event control; no automatic revenue transfer is created.","required":["collaboration"],"properties":{"collaboration":{"type":"ref","ref":"#ticketCollaboration"}}},"ticketCollaborationRevoked":{"type":"object","description":"The primary organizer revoked a co-organizer collaboration. The co-organizer loses operational control; nothing is unwound on the payment rail (revenueShareBps was only ever a manual-reconciliation intent).","required":["collaboration"],"properties":{"collaboration":{"type":"ref","ref":"#ticketCollaboration"}}},"ticketCollaboration":{"type":"object","description":"Organizer collaboration payload. revenueShareBps is a recorded MANUAL-RECONCILIATION intent only; ATM never settles ticket revenue against it.","required":["id","eventId","primaryOrganizerDid","coOrganizerDid","status","timestamp"],"properties":{"id":{"type":"string","maxLength":300},"eventId":{"type":"string","maxLength":300},"primaryOrganizerDid":{"type":"string","format":"did"},"coOrganizerDid":{"type":"string","format":"did"},"status":{"type":"string","knownValues":["pending","accepted","revoked"],"maxLength":16},"revenueShareBps":{"type":"integer","minimum":0,"maximum":10000,"description":"Recorded revenue-share INTENT in basis points, for MANUAL RECONCILIATION ONLY. ATM never transfers ticket revenue based on this value."},"timestamp":{"type":"string","format":"datetime"}}},"customerSegmentMessageRequested":{"type":"object","description":"The originating app asked ATM to fan a marketing message out to a computed customer cohort. ATM never sends marketing email itself — this event tells the app to perform its own send. Carries only the cohort key, the app's opaque message type, and the current member count; never buyer DIDs, emails, or PII.","required":["segmentKey","messageType","memberCount","requestedAt"],"properties":{"segmentKey":{"type":"string","knownValues":["at_risk_churn","high_value","lapsed"],"maxLength":32,"description":"Which computed cohort the message targets."},"messageType":{"type":"string","maxLength":64,"description":"App-defined opaque message identifier (e.g. a campaign id)."},"memberCount":{"type":"integer","minimum":0,"description":"Current number of members in the cohort at request time."},"requestedAt":{"type":"string","format":"datetime"}}},"recipientAuthorizationUpdated":{"type":"object","description":"A creator/recipient approved, blocked, or revoked this app's authorization to originate payments on their behalf. status=approved means the app may accept payments for recipientDid (within approvedPaymentTypes / approvedFeeShareBps); blocked/revoked means it must stop. Carries DIDs + the approved scope only — never buyer/creator PII.","required":["recipientDid","status","updatedAt"],"properties":{"recipientDid":{"type":"string","format":"did"},"status":{"type":"string","knownValues":["approved","blocked","revoked"],"maxLength":16},"approvedPaymentTypes":{"type":"array","maxLength":16,"items":{"type":"string","maxLength":64},"description":"Payment types the recipient approved this app to originate. Empty/absent when status is not approved."},"approvedFeeShareBps":{"type":"integer","minimum":0,"maximum":10000,"description":"App fee share approved for this recipient, in basis points. Null when status is not approved."},"updatedAt":{"type":"string","format":"datetime"}}},"main":{"type":"procedure","description":"Optional app-implemented XRPC receiver for ATM outbound events. ATM calls this with service-auth; signed HTTP webhooks remain the universal fallback.","input":{"encoding":"application/json","schema":{"type":"object","required":["id","type","created","apiVersion","data"],"properties":{"id":{"type":"string","description":"ATM delivery id. Receivers should use this for idempotency."},"type":{"type":"ref","ref":"#eventType","description":"ATM event type, such as payment.completed or tickets.issued."},"created":{"type":"integer","description":"Unix timestamp, in seconds, when ATM built the event envelope."},"apiVersion":{"type":"string","description":"ATM outbound event envelope version."},"environment":{"type":"string","knownValues":["test","live"],"description":"ATM app environment for this delivery."},"data":{"type":"union","refs":["#appWebhookTest","#paymentCompleted","#paymentFailed","#paymentRefunded","#paymentRefundUpdated","#paymentDisputed","#paymentDisputeClosed","#subscriptionInvoicePaid","#subscriptionUpdated","#subscriptionCancelled","#subscriptionPaymentFailed","#subscriptionRecovered","#payerRecordRequested","#payerClaimed","#creatorProofRequested","#attestationUpdated","#productUpdated","#productArchived","#productDeleted","#ticketHoldCreated","#ticketHoldExpired","#ticketsIssued","#ticketVoided","#ticketRefunded","#ticketCheckedIn","#ticketFormSubmitted","#ticketWaitlistJoined","#ticketWaitlistOffered","#ticketCollaborationInvited","#ticketCollaborationAccepted","#ticketCollaborationRevoked","#customerSegmentMessageRequested","#recipientAuthorizationUpdated"],"description":"Event-specific payload. See the named payload defs in this lexicon; ATM validates event payloads by type before delivery. This published schema is the protocol contract, not an exhaustive list of webhook fields: over the signed HTTP webhook ATM additionally delivers private fulfillment fields (such as customer contact and shipping) that apps need to fulfill orders but that are intentionally NOT part of this published protocol schema and are never written to public PDS records."}}}},"output":{"encoding":"application/json","schema":{"type":"object","properties":{"accepted":{"type":"boolean","description":"Optional acknowledgement. Any 2xx response means the receiver accepted the event."}}}},"errors":[{"name":"Rejected","description":"The receiver rejected the event. ATM may retry non-2xx HTTP responses."}]}}}