> ## Documentation Index
> Fetch the complete documentation index at: https://docs.air3.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Ticketing & Events

> Turn every venue scan into a portable attendance credential fans can reuse for loyalty rewards, presale access, and partner discounts.

Traditional event tickets are one-time-use and forgotten after the show. AIR Kit lets you transform every venue scan into a **permanent, portable attendance credential** — proof the fan was there, reusable for loyalty rewards, presale access, partner discounts, and cross-brand partnerships.

<Tabs>
  <Tab title="For business">
    ## What Changes With AIR Kit

    * **Every scan becomes a credential** — Venue check-in issues a verifiable "attended this event" proof into the fan's AIR Account. No app to open, no action from the fan
    * **Fan loyalty without a new program** — Fans who reach an attendance threshold can be upgraded to a "Loyal Fan" credential automatically
    * **Gated access that partners can trust** — VIP lounges, meet-and-greets, and presales unlock for verified attendees. The verifier learns only that the fan qualifies
    * **Cross-brand fan benefits** — Merchandise, hotel, and streaming partners accept the attendance credential directly. No bilateral API between you and each partner
    * **Anti-scalping** — Secondary ticket access can be gated behind an attendance credential from a prior event

    ## What Your Fans Experience

    Nothing changes at the door. The fan scans in as they do today; the credential issues silently in the background.

    Later, at a partner or your own presale, the fan authenticates with their AIR Account and the benefit unlocks. No code to enter, no account linking.

    ## Next Steps

    <CardGroup cols={2}>
      <Card title="Compliance FAQ" icon="shield-check" href="/solutions/compliance-faq">
        GDPR, PII, and data residency answers.
      </Card>

      <Card title="Partner Economics" icon="coins" href="/solutions/partner-economics">
        How the revenue model works for issuers and verifiers.
      </Card>

      <Card title="Loyalty & Rewards" icon="gift" href="/products/loyalty/business">
        Build tier-based loyalty on top of attendance credentials.
      </Card>

      <Card title="Talk to our team" icon="handshake" href="https://air3.com/partner-with-us">
        Start a partnership conversation.
      </Card>
    </CardGroup>
  </Tab>

  <Tab title="For developers">
    ## What You Can Build

    * **Attendance credentials** — Issue a verifiable "I attended X event" badge at check-in
    * **Fan loyalty tiers** — Auto-upgrade fans after 5 attended events to "Loyal Fan" credential
    * **Exclusive access gating** — Gate VIP lounges, artist meet-and-greets, and presales to verified attendees
    * **Cross-brand fan credentials** — Share attendance proof with partner brands (merchandise, hotels, streaming). [Try it live](https://demo.air3.com/try-it-live/hotel-package): the ticketing site issues, the hotel verifies
    * **Anti-scalping** — Gate secondary ticket access behind an attendance credential from a prior event

    ## Architecture

    ```mermaid theme={null}
    graph TD
        A[Fan arrives at venue] --> B["Venue scanner / check-in system"]
        B -->|"Scan detects fan's AIR Account email"| C[On-demand issuance]
        C --> D["Attendance Credential\nin Fan's AIR Account"]

        D --> E{Fan uses credential later}
        E --> F[Claim loyalty reward]
        E --> G[Access VIP presale]
        E --> H[Redeem partner discount]
        E --> I[Prove attendance history]
    ```

    ## Recommended Schema

    ```json theme={null}
    {
      "title": "Event Attendance",
      "description": "Verifiable proof of physical attendance at a live event",
      "properties": {
        "eventId": {
          "type": "string",
          "description": "Unique event identifier"
        },
        "eventName": {
          "type": "string",
          "description": "Display name — e.g. 'Coachella 2025 Day 1'"
        },
        "venue": {
          "type": "string",
          "description": "Venue name and city"
        },
        "attendedAt": {
          "type": "string",
          "format": "date-time",
          "description": "Timestamp of check-in scan"
        },
        "ticketTier": {
          "type": "string",
          "enum": ["General", "VIP", "Backstage", "Artist"],
          "description": "Ticket category"
        },
        "organizerId": {
          "type": "string",
          "description": "Issuing organizer / promoter identifier"
        }
      },
      "required": ["eventId", "eventName", "attendedAt", "organizerId"]
    }
    ```

    ## Implementation

    ### Step 1 — Issue attendance credential at check-in

    Your venue scanner calls your backend on each valid scan. The backend issues the credential on-demand — the fan does nothing, no wallet open, no UX friction at the door.

    ```javascript theme={null}
    // venue-checkin.js
    const { getPartnerJwt } = require('./lib/jwt');
    // issuer-controlled helpers backed by your signing keys
    const { buildVc, signVc, encryptToHolder } = require('./lib/credential');

    const BASE_URL = 'https://api.sandbox.mocachain.org/v1';

    async function issueAttendanceCredential({ fanEmail, eventDetails }) {
      const token = await getPartnerJwt();

      // Resolve the fan's AIR Account
      const init = await fetch(`${BASE_URL}/auth/initialize-user`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'x-partner-auth': token },
        body: JSON.stringify({ email: fanEmail }),
      }).then((r) => r.json());

      // Build, sign (SD-JWT VC), and encrypt the credential to the holder
      const schemaId = process.env.ATTENDANCE_CREDENTIAL_ID;
      const vc = buildVc({
        holderDid: init.did,
        schemaId,
        credentialSubject: {
          eventId: eventDetails.id,
          eventName: eventDetails.name,
          venue: eventDetails.venue,
          attendedAt: new Date().toISOString(),
          ticketTier: eventDetails.ticketTier,   // "General" | "VIP" | "Backstage"
          organizerId: process.env.ORGANIZER_ID,
        },
      });
      const encrypted = encryptToHolder(signVc(vc), init.publicKey);

      // Store the encrypted envelope in DStorage
      const res = await fetch(`${BASE_URL}/dstorage/vcs`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'x-partner-auth': token },
        body: JSON.stringify({
          holderDid: init.did,
          schemaId,
          expiresAt: vc.expirationDate,
          data: encrypted.encryptedData,
          iv: encrypted.iv,
          authTag: encrypted.authTag,
          encryptedKey: encrypted.dataEncPublicKey,
          externalId: vc.id,
        }),
      });
      if (!res.ok) throw new Error(`Attendance issuance failed: ${res.status}`);
      const { storagePath } = await res.json();
      return storagePath;
    }

    // Called by your ticketing system on each valid scan
    app.post('/api/checkin', async (req, res) => {
      const { fanEmail, eventId } = req.body;
      const event = await getEventDetails(eventId);
      const storagePath = await issueAttendanceCredential({ fanEmail, eventDetails: event });
      res.json({ success: true, storagePath });
    });
    ```

    ### Step 2 — Gate VIP presale to verified attendees

    ```javascript theme={null}
    // presale-gate.js  (frontend)
    import { AirService } from '@mocanetwork/airkit';

    import { AirService, BUILD_ENV } from "@mocanetwork/airkit";

    const airService = new AirService({ partnerId: process.env.PARTNER_ID });
    await airService.init({ buildEnv: BUILD_ENV.SANDBOX });

    async function canAccessPresale() {
      const result = await airService.verifyCredential({
        programId: process.env.PRESALE_VERIFY_PROGRAM_ID,
        // Verifier program rule: organizerId === process.env.ORGANIZER_ID
        // (attended at least 1 prior event by this organizer)
      });
      return result.status === 'COMPLIANT';
    }

    const isVerifiedFan = await canAccessPresale();
    if (isVerifiedFan) {
      showPresaleRegistration();
    } else {
      showMessage('Presale access requires verified attendance at a prior event.');
    }
    ```

    ### Step 3 — Auto-upgrade fans to loyalty tiers after N events

    ```javascript theme={null}
    // loyalty-tier-check.js — called after each attendance credential issuance
    async function checkAndIssueLoyaltyTier(fanEmail) {
      const attendedCount = await getAttendanceCount(fanEmail); // your DB

      if (attendedCount === 5)  await issueLoyaltyTier({ fanEmail, tier: 'Loyal Fan' });
      if (attendedCount === 20) await issueLoyaltyTier({ fanEmail, tier: 'Super Fan' });
    }

    // issueLoyaltyTier uses the same on-demand issuance pattern — see AIR for Loyalty guide
    ```

    ## Zero-Friction Fan UX

    The key advantage for events: **fans never interact with the credential system at the door**. They scan their ticket as normal, the credential lands in their AIR Account in the background, and they use it the next time they want a reward or presale.

    <Steps>
      <Step title="Fan scans ticket at the door">
        No app to open, no wallet prompt. Exactly the same experience as today.
      </Step>

      <Step title="Your backend issues the attendance credential">
        On-demand issuance fires silently. The credential lands in the fan's AIR Account, encrypted to them.
      </Step>

      <Step title="Fan opens the app the next day">
        Sees a notification: "You earned a Verified Attendee credential for Coachella 2025."
      </Step>

      <Step title="Fan uses the credential">
        One tap to register for the presale, claim a merchandise discount, or prove their fan tier to a partner brand.
      </Step>
    </Steps>

    ## Examples

    <CardGroup cols={2}>
      <Card title="Fan Attendance — live demo" icon="play" href="https://demo.air3.com/try-it-live/tour-record">
        Check in at the concert hall, then buy a record sold only to fans who went to the show.
      </Card>

      <Card title="Cross-brand package — live demo" icon="play" href="https://demo.air3.com/try-it-live/hotel-package">
        The ticketing site issues the credential and a hotel verifies it for a festival package.
      </Card>

      <Card title="Fan Attendance — Issuer" icon="github" href="https://github.com/MocaNetwork/air-examples/tree/main/fan-attendance/issuer">
        Venue check-in app: issues attendance credential when the fan scans in at the event.
      </Card>

      <Card title="Fan Attendance — Verifier" icon="github" href="https://github.com/MocaNetwork/air-examples/tree/main/fan-attendance/verifier">
        Merch store app: verifies attendance and unlocks rewards (e.g. discount, exclusive offer).
      </Card>

      <Card title="VIP Status Portability — Issuer" icon="github" href="https://github.com/MocaNetwork/air-examples/tree/main/vip-status-portability/issuer">
        Airline loyalty app: issues tier credential; user carries status to partner brands.
      </Card>

      <Card title="VIP Status Portability — Verifier" icon="github" href="https://github.com/MocaNetwork/air-examples/tree/main/vip-status-portability/verifier">
        Hotel chain app: verifies tier and grants equivalent perks (e.g. room upgrade, lounge).
      </Card>
    </CardGroup>

    ## Next Steps

    <Columns cols={2}>
      <Card title="AIR for Loyalty & Rewards" icon="gift" href="/products/loyalty/developers">
        Build tier-based loyalty on top of attendance credentials.
      </Card>

      <Card title="On-demand Issuance — API" icon="code" href="/api-reference/issuance-api">
        Full endpoint reference and error handling.
      </Card>

      <Card title="Architecture & Data Flow" icon="diagram-project" href="/technicals/architecture">
        End-to-end system overview.
      </Card>
    </Columns>
  </Tab>
</Tabs>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.