@playaos/api-client 0.54.0 → 0.55.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -144,6 +144,7 @@ interface ApplicationAdmin extends Application {
144
144
  reviewedAt: string | null;
145
145
  }
146
146
  interface AdminNotificationPrefs {
147
+ shiftCoverageAlerts: boolean;
147
148
  applications: boolean;
148
149
  payments: boolean;
149
150
  shifts: boolean;
@@ -163,6 +164,7 @@ interface MemberDevice {
163
164
  updatedAt: string | null;
164
165
  }
165
166
  interface ImportantDate {
167
+ slug?: string | null;
166
168
  id: string;
167
169
  title: string;
168
170
  description: string | null;
@@ -204,6 +206,7 @@ interface SummerCampRsvpInput {
204
206
  type PhotoExportJobStatus = "queued" | "processing" | "completed" | "failed";
205
207
  /** Admin member-photo ZIP export job (PLA-1217). */
206
208
  interface PhotoExportJob {
209
+ startedAt?: string | null;
207
210
  id: string;
208
211
  status: PhotoExportJobStatus;
209
212
  fileName: string;
@@ -217,6 +220,8 @@ interface PhotoExportJob {
217
220
  completedAt: string | null;
218
221
  }
219
222
  interface CreatePhotoExportInput {
223
+ attending?: "true" | "all";
224
+ year?: number;
220
225
  role?: string;
221
226
  status?: string;
222
227
  search?: string;
@@ -583,6 +588,7 @@ interface Account {
583
588
  [key: string]: unknown;
584
589
  }
585
590
  interface CampDocument {
591
+ externalUrl?: string | null;
586
592
  id: string;
587
593
  orgId: string;
588
594
  name: string;
@@ -809,6 +815,7 @@ interface MemberDeactivateResponse {
809
815
  status: "inactive";
810
816
  }
811
817
  interface WaiverSection {
818
+ format?: "html" | "text";
812
819
  id: string;
813
820
  heading: string;
814
821
  body: string;
@@ -924,7 +931,7 @@ interface ApplicationEvent {
924
931
  * Widening the server list without widening this union lets a value escape
925
932
  * the declared type through the cast in `client.ts` — see PLA-1199.
926
933
  */
927
- type: "status_change" | "note_added" | "tags_updated" | "score_set" | "message_sent" | "message_received" | "approved" | "rejected" | "waitlisted" | "interview_invite_sent" | "interview_scheduled_manually" | "interview_completed" | "interviewer_assigned" | "red_flag_added";
934
+ type: "status_change" | "note_added" | "tags_updated" | "score_set" | "message_sent" | "message_received" | "approved" | "rejected" | "waitlisted" | "interview_invite_sent" | "interview_scheduled_manually" | "interview_completed" | "interviewer_assigned" | "red_flag_added" | "referrer_updated";
928
935
  timestamp: string;
929
936
  fromStatus?: string | null;
930
937
  toStatus?: string;
@@ -1087,6 +1094,7 @@ interface SapAllocation {
1087
1094
  totalAssigned: number;
1088
1095
  }
1089
1096
  interface UpdateSapAllocationInput {
1097
+ year?: number;
1090
1098
  totalAllocated: number;
1091
1099
  notes?: string | null;
1092
1100
  }
@@ -1098,6 +1106,7 @@ interface SapDayAllocation {
1098
1106
  notes: string | null;
1099
1107
  }
1100
1108
  interface UpsertSapDayAllocationInput {
1109
+ year?: number;
1101
1110
  accessDate: string;
1102
1111
  slotsAvailable: number;
1103
1112
  notes?: string | null;
@@ -1113,6 +1122,7 @@ interface SapAssignment {
1113
1122
  notes: string | null;
1114
1123
  }
1115
1124
  interface CreateSapAssignmentInput {
1125
+ year?: number;
1116
1126
  userId: string;
1117
1127
  sapNumber?: string | null;
1118
1128
  vehicleDescription?: string | null;
@@ -1282,6 +1292,7 @@ interface Meeting {
1282
1292
  dateOptions: MeetingDateOption[];
1283
1293
  }
1284
1294
  interface CreateMeetingInput {
1295
+ notifyMembers?: boolean;
1285
1296
  title: string;
1286
1297
  description?: string | null;
1287
1298
  isMandatory: boolean;
@@ -1310,6 +1321,7 @@ interface Scholarship {
1310
1321
  discountCodeId: string | null;
1311
1322
  }
1312
1323
  interface CreateScholarshipInput {
1324
+ providerManaged?: boolean;
1313
1325
  userId: string;
1314
1326
  promoCode: string;
1315
1327
  discountAmount: number;
@@ -1353,124 +1365,1469 @@ interface VehiclePassUpdateInput {
1353
1365
  vehiclePassStatus?: VehiclePassStatus | null;
1354
1366
  vehiclePassConfirmation?: string | null;
1355
1367
  }
1356
- //#endregion
1357
- //#region src/client.d.ts
1358
- interface ClientOptions {
1359
- /** Base URL for authenticated /api/v1 routes, e.g. https://api.playaos.app */
1360
- baseUrl: string;
1361
- /** Optional base URL for /api/embed/v1 routes when they live on a different host. */
1362
- embedBaseUrl?: string;
1363
- /** API key in the format pk_live_* */
1364
- apiKey: string;
1365
- /**
1366
- * Supabase session JWT of the acting member, sent as `X-PlayaOS-Member-Token`
1367
- * on every /api/v1 call (PLA-1195). Member-scoped endpoints (a member's own
1368
- * dues, payments, application, shelter, shifts signup, …) require it and
1369
- * return 401 without it. Org-level endpoints do not require it, but a token
1370
- * that is sent must still verify — an expired or invalid one is a 401 on any
1371
- * /api/v1 route that installs the member middleware. Prefer
1372
- * `client.withMember(token)` to derive a per-request client from a shared
1373
- * server-side one rather than constructing a client per user.
1374
- */
1375
- memberToken?: string;
1368
+ /** Self-only fields needed to enter the member portal; never includes auth/provider tokens. */
1369
+ interface MemberSelfProfile {
1370
+ id: string;
1371
+ name: string | null;
1372
+ email: string | null;
1373
+ role: string | null;
1374
+ isDeveloper: boolean | null;
1375
+ firstName: string;
1376
+ lastName: string;
1377
+ phone: string | null;
1378
+ emergencyContactName: string | null;
1379
+ emergencyContactPhone: string | null;
1380
+ dietaryRestrictions: string[] | null;
1381
+ tshirtSize: string | null;
1382
+ profilePhotoPath: string | null;
1383
+ onboardingPasswordDone: boolean | null;
1384
+ playaName: string | null;
1385
+ homeCity: string | null;
1386
+ bio: string | null;
1387
+ referralCode: string | null;
1388
+ otherAllergies: string | null;
1389
+ hasEpipen: boolean | null;
1390
+ }
1391
+ interface MemberBootstrap {
1392
+ year: number;
1393
+ profile: MemberSelfProfile;
1394
+ campYear: {
1395
+ transportMode: string | null;
1396
+ attendanceResponse: string | null;
1397
+ shelterWizardDone: boolean | null;
1398
+ } | null;
1399
+ confirmedShelterAssignment: {
1400
+ id: string;
1401
+ } | null;
1402
+ unsignedDocuments: Array<{
1403
+ id: string;
1404
+ name: string;
1405
+ description: string | null;
1406
+ content: string | WaiverContent | null;
1407
+ filePath: string | null;
1408
+ }>;
1376
1409
  }
1377
- export declare class PlayaOSClient {
1378
- private readonly baseUrl;
1379
- private readonly embedBaseUrl;
1380
- private readonly apiKey;
1381
- private readonly memberToken;
1382
- constructor(opts: ClientOptions);
1383
- /** Credentials for /api/v1 calls; the embed surface uses `apiKey` alone as the camp key. */
1384
- private get auth();
1385
- /**
1386
- * Derive a client that acts as one member (PLA-1195): same host and org key,
1387
- * plus the member's Supabase session JWT on every /api/v1 call. Use this in a
1388
- * server that holds one org key and serves many signed-in members.
1389
- */
1390
- withMember(memberToken: string): PlayaOSClient;
1391
- /**
1392
- * Admin dual-path (PLA-1203): when the client has a memberToken, call `/api/v1`
1393
- * (org key + X-PlayaOS-Member-Token). Otherwise keep the legacy embed-admin
1394
- * Bearer-JWT path so published consumers without withMember() still work.
1395
- */
1396
- private adminV1OrEmbed;
1397
- /** Resolve admin credential: memberToken clients skip accessToken; embed path requires it. */
1398
- private adminAccess;
1399
- readonly members: {
1400
- /** Presigned profile-photo upload (PLA-1263). PUT the bytes, then setPhoto. */
1401
- createPhotoUploadUrl: (payload: {
1402
- contentType: "image/jpeg" | "image/png" | "image/webp";
1403
- }, opts?: {
1404
- signal?: AbortSignal;
1405
- }) => Promise<{
1406
- uploadUrl: string;
1407
- path: string;
1408
- token: string;
1409
- key: string;
1410
- }>;
1411
- setPhoto: (payload: {
1412
- key: string;
1413
- }, opts?: {
1414
- signal?: AbortSignal;
1415
- }) => Promise<{
1416
- avatarUrl: string;
1417
- }>;
1418
- deletePhoto: (opts?: {
1419
- signal?: AbortSignal;
1420
- }) => Promise<{
1421
- success: boolean;
1422
- }>;
1423
- /** Active push device tokens for the acting member (PLA-1261). */
1424
- listDevices: (opts?: {
1425
- signal?: AbortSignal;
1426
- }) => Promise<MemberDevice[]>;
1427
- registerDevice: (payload: {
1428
- token: string;
1429
- platform: "ios" | "android";
1430
- environment?: "sandbox" | "production";
1431
- }, opts?: {
1432
- signal?: AbortSignal;
1433
- }) => Promise<{
1410
+ interface MemberDashboard {
1411
+ year: number;
1412
+ profile: MemberSelfProfile;
1413
+ gateInput: {
1414
+ hasPaidBaseDues: boolean;
1415
+ hasPaidRvDues: boolean;
1416
+ ownsRvShelter: boolean;
1417
+ hasSignedWaiver: boolean;
1418
+ arrivalDate: string | null;
1419
+ departureDate: string | null;
1420
+ rvLengthFt: number | null;
1421
+ rvAmperage: number | null;
1422
+ name: string | null;
1423
+ phone: string | null;
1424
+ emergencyContactName: string | null;
1425
+ emergencyContactPhone: string | null;
1426
+ dietaryRestrictions: string[] | null;
1427
+ tshirtSize: string | null;
1428
+ transportMode: string | null;
1429
+ isAdmin: boolean;
1430
+ hasInterviewerSetup: boolean;
1431
+ hasProfilePhoto: boolean;
1432
+ };
1433
+ pendingDocuments: Array<{
1434
+ id: string;
1435
+ name: string;
1436
+ }>;
1437
+ hasShelterAssignment: boolean;
1438
+ upcomingShiftCount: number;
1439
+ importantDates: Array<{
1440
+ id: string;
1441
+ title: string;
1442
+ date: string;
1443
+ }>;
1444
+ upcomingMeetings: Array<{
1445
+ id: string;
1446
+ title: string;
1447
+ isMandatory: boolean;
1448
+ earliestDate: string;
1449
+ hasRsvped: boolean;
1450
+ }>;
1451
+ campSettings: Record<string, string>;
1452
+ yearsAttended: number[];
1453
+ }
1454
+ interface MemberOnboardingUpdate {
1455
+ firstName?: string;
1456
+ lastName?: string;
1457
+ phone?: string | null;
1458
+ emergencyContactName?: string | null;
1459
+ emergencyContactPhone?: string | null;
1460
+ dietaryRestrictions?: string[];
1461
+ tshirtSize?: string | null;
1462
+ bikeRentalInterest?: boolean | null;
1463
+ onboardingPasswordDone?: true;
1464
+ transportMode?: "personal_vehicle" | "rv" | "burner_bus" | "rideshare" | "other" | "burner_air" | "private_plane" | null;
1465
+ attendanceResponse?: "attending" | "not_attending" | "undecided";
1466
+ shelterWizardDone?: true;
1467
+ year?: number;
1468
+ }
1469
+ type ApplicationWorkflowInput = {
1470
+ action: "invite";
1471
+ } | {
1472
+ action: "assign_interviewer";
1473
+ interviewerId: string | null;
1474
+ } | {
1475
+ action: "schedule_manual";
1476
+ scheduledAt: string;
1477
+ } | {
1478
+ action: "red_flag";
1479
+ flag: string;
1480
+ } | {
1481
+ action: "interview_note";
1482
+ note: string;
1483
+ } | {
1484
+ action: "referrer";
1485
+ referrerUserId: string | null;
1486
+ } | {
1487
+ action: "transition";
1488
+ to: "approved" | "rejected" | "waitlisted" | "interviewed";
1489
+ reason?: string;
1490
+ activateMemberOnApproval?: boolean;
1491
+ };
1492
+ interface ApplicationWorkflowOptions {
1493
+ admins: {
1494
+ id: string;
1495
+ name: string | null;
1496
+ }[];
1497
+ workload: {
1498
+ interviewerId: string;
1499
+ interviewerName: string | null;
1500
+ pendingInterviews: number;
1501
+ completedInterviews: number;
1502
+ totalAssigned: number;
1503
+ lastAssignedAt: string | null;
1504
+ }[];
1505
+ referrers: {
1506
+ id: string;
1507
+ displayName: string;
1508
+ }[];
1509
+ }
1510
+ interface ApplicationActivityItem {
1511
+ id: string;
1512
+ type: "audit" | "message";
1513
+ timestamp: string;
1514
+ action?: string;
1515
+ details?: Record<string, unknown>;
1516
+ direction?: "inbound" | "outbound";
1517
+ subject?: string;
1518
+ body?: string;
1519
+ fromEmail?: string;
1520
+ actorName?: string;
1521
+ }
1522
+ type ShiftAdminOperation = {
1523
+ action: "create_type";
1524
+ name: string;
1525
+ description?: string;
1526
+ durationHours: number;
1527
+ } | {
1528
+ action: "update_type";
1529
+ id: string;
1530
+ name?: string;
1531
+ description?: string;
1532
+ durationHours?: number;
1533
+ } | {
1534
+ action: "delete_type";
1535
+ id: string;
1536
+ } | {
1537
+ action: "create_shift";
1538
+ shiftTypeId: string;
1539
+ shiftDate: string;
1540
+ startTime: string;
1541
+ endTime: string;
1542
+ maxSlots: number;
1543
+ notes?: string;
1544
+ } | {
1545
+ action: "update_shift";
1546
+ id: string;
1547
+ maxSlots?: number;
1548
+ notes?: string;
1549
+ startTime?: string;
1550
+ endTime?: string;
1551
+ } | {
1552
+ action: "delete_shift";
1553
+ id: string;
1554
+ } | {
1555
+ action: "bulk_create";
1556
+ shiftTypeId: string;
1557
+ dates: string[];
1558
+ startTime: string;
1559
+ endTime: string;
1560
+ maxSlots: number;
1561
+ } | {
1562
+ action: "clear_day";
1563
+ date: string;
1564
+ } | {
1565
+ action: "copy_day";
1566
+ sourceDate: string;
1567
+ targetDate: string;
1568
+ } | {
1569
+ action: "remove_signup";
1570
+ id: string;
1571
+ } | {
1572
+ action: "signup_role";
1573
+ id: string;
1574
+ role: string;
1575
+ };
1576
+ interface ShiftAdminOperationResult {
1577
+ id?: string;
1578
+ createdCount?: number;
1579
+ deletedCount?: number;
1580
+ copiedCount?: number;
1581
+ skippedCount?: number;
1582
+ }
1583
+ interface OwnerShelterPatch {
1584
+ name?: string | null;
1585
+ maxOccupants?: number;
1586
+ rvLengthFt?: number | null;
1587
+ rvAmperage?: 30 | 50 | null;
1588
+ shelterLengthFt?: number | null;
1589
+ shelterWidthFt?: number | null;
1590
+ shelterHeightFt?: number | null;
1591
+ needsPower?: boolean;
1592
+ needsPumping?: boolean;
1593
+ shelterDescription?: string | null;
1594
+ }
1595
+ interface OwnerShelterCreate extends OwnerShelterPatch {
1596
+ year?: number;
1597
+ shelterType: "rv" | "shiftpod" | "tent" | "hexayurt" | "other" | "car" | "truck" | "van" | "trailer";
1598
+ maxOccupants: number;
1599
+ payerUserId?: string | null;
1600
+ mateUserIds?: string[];
1601
+ completeWizard?: boolean;
1602
+ hasSpaceForOthers?: boolean;
1603
+ askingPrice?: number | null;
1604
+ }
1605
+ interface MemberShelter {
1606
+ id: string;
1607
+ name: string | null;
1608
+ shelterType: string;
1609
+ maxOccupants: number;
1610
+ rvLengthFt: number | null;
1611
+ rvAmperage: number | null;
1612
+ shelterLengthFt: number | null;
1613
+ shelterWidthFt: number | null;
1614
+ shelterHeightFt: number | null;
1615
+ needsPower: boolean | null;
1616
+ needsPumping: boolean | null;
1617
+ shelterDescription: string | null;
1618
+ members: Array<{
1619
+ id: string;
1620
+ name: string | null;
1621
+ isOwner: boolean;
1622
+ assignmentId: string;
1623
+ status: string;
1624
+ }>;
1625
+ }
1626
+ interface MemberShelterPage {
1627
+ currentAssignment: {
1628
+ id: string;
1629
+ isOwner: boolean;
1630
+ shelter: MemberShelter;
1631
+ } | null;
1632
+ availableShelters: MemberShelter[];
1633
+ pendingInvites: Array<{
1634
+ id: string;
1635
+ shelter: {
1434
1636
  id: string;
1435
- registered: boolean;
1637
+ name: string | null;
1638
+ shelterType: string;
1639
+ ownerName: string | null;
1640
+ };
1641
+ }>;
1642
+ }
1643
+ interface DocumentWriteInput {
1644
+ title: string;
1645
+ type: string;
1646
+ body?: unknown;
1647
+ description?: string | null;
1648
+ requiresSignature?: boolean;
1649
+ year?: number;
1650
+ deadline?: string | null;
1651
+ filePath?: string | null;
1652
+ externalUrl?: string | null;
1653
+ isActive?: boolean;
1654
+ }
1655
+ interface ContractSection {
1656
+ id: string;
1657
+ title: string;
1658
+ bodyHtml: string;
1659
+ sortOrder: number;
1660
+ }
1661
+ type ShiftAdminWorkflow = {
1662
+ action: "assign_member";
1663
+ shiftId: string;
1664
+ memberId: string;
1665
+ forceAssign?: boolean;
1666
+ } | {
1667
+ action: "assign_shelter";
1668
+ shiftId: string;
1669
+ shelterId: string;
1670
+ forceAssign?: boolean;
1671
+ } | {
1672
+ action: "publish";
1673
+ };
1674
+ interface ShiftAdminWorkflowResult {
1675
+ assignedCount?: number;
1676
+ skippedCount?: number;
1677
+ notificationsSent?: number;
1678
+ notificationsFailed?: number;
1679
+ totalMembers?: number;
1680
+ }
1681
+ interface ShiftPlannerData {
1682
+ year: number;
1683
+ members: Array<{
1684
+ id: string;
1685
+ name: string;
1686
+ email: string | null;
1687
+ dietaryRestrictions: string[] | null;
1688
+ shiftCapabilities: string[] | null;
1689
+ arrivalDate: string | null;
1690
+ departureDate: string | null;
1691
+ shelters: Array<{
1692
+ id: string;
1693
+ name: string;
1694
+ shelterType: string;
1436
1695
  }>;
1437
- deleteDevice: (payload: {
1438
- token: string;
1439
- }, opts?: {
1440
- signal?: AbortSignal;
1441
- }) => Promise<{
1442
- unregistered: boolean;
1696
+ }>;
1697
+ shelters: Array<{
1698
+ id: string;
1699
+ name: string;
1700
+ shelterType: string;
1701
+ }>;
1702
+ }
1703
+ interface MemberBikeStatus {
1704
+ bikeTypes: Array<{
1705
+ id: string;
1706
+ name: string;
1707
+ description: string | null;
1708
+ available: number;
1709
+ }>;
1710
+ rental: {
1711
+ id: string;
1712
+ status: string;
1713
+ bikeType: string;
1714
+ bikeNumber: string | null;
1715
+ } | null;
1716
+ hasSignedWaiver: boolean;
1717
+ year: number;
1718
+ }
1719
+ interface MemberProfileUpdate {
1720
+ firstName?: string;
1721
+ lastName?: string;
1722
+ phone?: string | null;
1723
+ emergencyContact?: string | null;
1724
+ emergencyContactName?: string | null;
1725
+ emergencyContactRelationship?: string | null;
1726
+ emergencyContactPhone?: string | null;
1727
+ birthday?: string | null;
1728
+ playaName?: string | null;
1729
+ bio?: string | null;
1730
+ homeCity?: string | null;
1731
+ otherAllergies?: string | null;
1732
+ dietaryRestrictions?: string[];
1733
+ teamInterests?: string[];
1734
+ hasEpipen?: boolean;
1735
+ tshirtSize?: string | null;
1736
+ referredByUserId?: string | null;
1737
+ socialMedia?: {
1738
+ instagram?: string | null;
1739
+ twitter?: string | null;
1740
+ tiktok?: string | null;
1741
+ facebook?: string | null;
1742
+ } | null;
1743
+ showSocialsInDirectory?: boolean;
1744
+ directoryNameDisplay?: "name" | "playa_name" | "both";
1745
+ }
1746
+ interface MemberTravelUpdate {
1747
+ arrivalDate?: string | null;
1748
+ departureDate?: string | null;
1749
+ buildArrivalDate?: string | null;
1750
+ burnerBusArrivalDate?: string | null;
1751
+ burnerBusDepartureDate?: string | null;
1752
+ burnerAirArrivalDate?: string | null;
1753
+ burnerAirDepartureDate?: string | null;
1754
+ privatePlaneArrivalDate?: string | null;
1755
+ privatePlaneDepartureDate?: string | null;
1756
+ burnerBusArrivalTime?: string | null;
1757
+ burnerBusDepartureTime?: string | null;
1758
+ burnerAirArrivalTime?: string | null;
1759
+ burnerAirDepartureTime?: string | null;
1760
+ privatePlaneArrivalTime?: string | null;
1761
+ privatePlaneDepartureTime?: string | null;
1762
+ arrivalTime?: "morning" | "afternoon" | "evening" | null;
1763
+ departureTime?: "morning" | "afternoon" | "evening" | null;
1764
+ transportMode?: MemberOnboardingUpdate["transportMode"];
1765
+ departureTransportMode?: MemberOnboardingUpdate["transportMode"];
1766
+ isBuildWeek?: boolean;
1767
+ isStrike?: boolean;
1768
+ wantsBikeRental?: boolean;
1769
+ attendanceResponse?: "attending" | "not_attending" | "undecided";
1770
+ containerService?: string | null;
1771
+ containerItemCount?: number | null;
1772
+ containerShippingNotes?: string | null;
1773
+ bikeTypePreference?: "ebike" | "pedal" | null;
1774
+ cookOrCleanPreference?: "cook" | "clean" | "no_preference" | null;
1775
+ }
1776
+ interface MemberSelfProfilePatch {
1777
+ profile?: MemberProfileUpdate;
1778
+ campYear?: MemberTravelUpdate;
1779
+ year?: number;
1780
+ }
1781
+ interface MemberProfileDetails {
1782
+ profile: { [K in keyof MemberProfileUpdate]-?: Exclude<MemberProfileUpdate[K], undefined> | null; } & {
1783
+ id: string;
1784
+ email: string | null;
1785
+ name: string | null;
1786
+ role: string | null;
1787
+ status: string | null;
1788
+ profilePhotoPath: string | null;
1789
+ referralCode: string;
1790
+ invitedAt: string | null;
1791
+ yearJoined: number | null;
1792
+ is747Alumni: boolean | null;
1793
+ createdAt: string | null;
1794
+ adminRoles: string[] | null;
1795
+ shiftCapabilities: string[] | null;
1796
+ };
1797
+ campYear: ({ [K in keyof MemberTravelUpdate]-?: Exclude<MemberTravelUpdate[K], undefined> | null; } & {
1798
+ year: number;
1799
+ ticketStatus: string | null;
1800
+ ticketConfirmationNumber: string | null;
1801
+ ticketNotes: string | null;
1802
+ hasWillCallTicket: boolean | null;
1803
+ }) | null;
1804
+ yearsAttended: number[];
1805
+ }
1806
+ interface MemberPushPreferences {
1807
+ shift_reminders: boolean;
1808
+ event_updates: boolean;
1809
+ camp_announcements: boolean;
1810
+ payment_reminders: boolean;
1811
+ document_requests: boolean;
1812
+ }
1813
+ interface MemberDocumentPage {
1814
+ defaultLegalName: string;
1815
+ documents: Array<{
1816
+ id: string;
1817
+ name: string;
1818
+ description: string | null;
1819
+ documentType: string;
1820
+ deadline: string | null;
1821
+ filePath: string | null;
1822
+ externalUrl: string | null;
1823
+ htmlContent: string | null;
1824
+ signatureId: string | null;
1825
+ isSigned: boolean;
1826
+ signedAt: string | null;
1827
+ }>;
1828
+ pastYearGroups: Array<{
1829
+ year: number;
1830
+ documents: Array<{
1831
+ id: string;
1832
+ name: string;
1833
+ description: string | null;
1834
+ filePath: string | null;
1835
+ externalUrl: string | null;
1443
1836
  }>;
1444
- /** The acting member's communication + (admin) notification preferences (PLA-1262). */
1445
- getPreferences: (opts?: {
1446
- signal?: AbortSignal;
1447
- }) => Promise<MemberPreferences>;
1448
- updatePreferences: (payload: {
1449
- emailMarketingOptIn: boolean;
1450
- adminNotifications?: AdminNotificationPrefs;
1451
- }, opts?: {
1452
- signal?: AbortSignal;
1453
- }) => Promise<MemberPreferences>;
1454
- list: (params?: {
1455
- role?: MemberRole;
1456
- status?: string;
1457
- /** Comma-separated roles; wins over `role` (e.g. `admin,member`). */
1458
- roles?: string;
1459
- /** Comma-separated statuses; wins over `status` (e.g. `active,inactive`). */
1460
- statuses?: string;
1461
- q?: string;
1462
- sortBy?: "name" | "email" | "role" | "status" | "createdAt";
1463
- sortOrder?: "asc" | "desc";
1464
- attending?: "true" | "false";
1465
- } & PaginationParams & {
1466
- /** Raw row offset — the members table's pager. Mutually exclusive with `cursor`. */
1467
- offset?: number;
1468
- }, opts?: {
1469
- signal?: AbortSignal;
1470
- }) => Promise<MembersListResponse>;
1471
- /**
1472
- * Full profile (phone, emergency contact). Requires a member token; pass
1473
- * `"me"` for the acting member — non-admins may fetch only themselves.
1837
+ }>;
1838
+ }
1839
+ interface MemberShiftView {
1840
+ arrivalDate: string | null;
1841
+ departureDate: string | null;
1842
+ shifts: Array<{
1843
+ signupId: string;
1844
+ shiftId: string;
1845
+ shiftTypeName: string;
1846
+ shiftDate: string;
1847
+ startTime: string | null;
1848
+ endTime: string | null;
1849
+ status: string | null;
1850
+ coworkers: string[];
1851
+ }>;
1852
+ }
1853
+ type AdminShelterOperation = {
1854
+ action: "approve" | "remove";
1855
+ assignmentId: string;
1856
+ } | {
1857
+ action: "status";
1858
+ assignmentId: string;
1859
+ status: string;
1860
+ } | {
1861
+ action: "assign" | "move";
1862
+ shelterId: string;
1863
+ userId: string;
1864
+ forceOverCapacity?: boolean;
1865
+ } | {
1866
+ action: "transfer";
1867
+ shelterId: string;
1868
+ newOwnerUserId: string;
1869
+ } | {
1870
+ action: "create";
1871
+ ownerUserId: string;
1872
+ data: OwnerShelterCreate;
1873
+ } | {
1874
+ action: "update";
1875
+ shelterId: string;
1876
+ data: OwnerShelterPatch;
1877
+ } | {
1878
+ action: "placement";
1879
+ shelterId: string;
1880
+ mapX: number | null;
1881
+ mapY: number | null;
1882
+ } | {
1883
+ action: "delete";
1884
+ shelterId: string;
1885
+ };
1886
+ interface MobileShifts {
1887
+ shifts: Array<{
1888
+ id: string;
1889
+ date: string;
1890
+ startTime: string | null;
1891
+ endTime: string | null;
1892
+ maxSlots: number;
1893
+ type: {
1894
+ id: string;
1895
+ name: string;
1896
+ description: string | null;
1897
+ };
1898
+ currentSignups: number;
1899
+ isFull: boolean;
1900
+ isSignedUp: boolean;
1901
+ isEligible: boolean;
1902
+ signupId?: string;
1903
+ signupStatus?: string | null;
1904
+ }>;
1905
+ profile: {
1906
+ arrivalDate: string | null;
1907
+ departureDate: string | null;
1908
+ status: string | null;
1909
+ };
1910
+ }
1911
+ interface AdminCampSettings {
1912
+ year: number;
1913
+ slotLimits: Record<string, number>;
1914
+ feeTiers: Array<{
1915
+ id: string;
1916
+ name: string;
1917
+ displayName: string;
1918
+ amount: string;
1919
+ }>;
1920
+ reminders: Array<{
1921
+ type: string;
1922
+ enabled: boolean;
1923
+ }>;
1924
+ contract: {
1925
+ campName: string;
1926
+ legalEntity: string;
1927
+ logoUrl: string | null;
1928
+ addressLines: string[];
1929
+ footerText: string | null;
1930
+ };
1931
+ }
1932
+ type CampSettingsOperation = {
1933
+ action: "slot_limits";
1934
+ limits: Record<string, number>;
1935
+ } | {
1936
+ action: "fee_tier";
1937
+ id: string;
1938
+ displayName: string;
1939
+ amount: number;
1940
+ } | {
1941
+ action: "reminder";
1942
+ type: "payment" | "onboarding" | "documents" | "logistics_undecided" | "photo_avatar" | "photo_fullsize" | "attendance_nudge";
1943
+ enabled: boolean;
1944
+ } | ({
1945
+ action: "contract";
1946
+ } & AdminCampSettings["contract"]);
1947
+ type AdminBikeOperation = {
1948
+ action: "checkout";
1949
+ rentalId: string;
1950
+ bikeInventoryId: string;
1951
+ } | {
1952
+ action: "return";
1953
+ rentalId: string;
1954
+ depositStatus: "refunded" | "forfeited";
1955
+ damageNotes?: string;
1956
+ } | {
1957
+ action: "add";
1958
+ bikeId: string;
1959
+ typeId: string;
1960
+ notes?: string;
1961
+ } | {
1962
+ action: "mark_paid";
1963
+ rentalId: string;
1964
+ confirmationNumber: string;
1965
+ } | {
1966
+ action: "bike_status";
1967
+ bikeId: string;
1968
+ status: "available" | "rented" | "maintenance" | "retired";
1969
+ notes?: string;
1970
+ } | {
1971
+ action: "rental_status";
1972
+ rentalId: string;
1973
+ status: "pending_payment" | "pending_waiver" | "reserved" | "checked_out" | "returned" | "cancelled";
1974
+ } | {
1975
+ action: "nudge_interest";
1976
+ } | {
1977
+ action: "booking_link";
1978
+ memberId: string;
1979
+ };
1980
+ interface AdminBikeOperationResult {
1981
+ success: true;
1982
+ sent?: number;
1983
+ failed?: number;
1984
+ }
1985
+ type AdminPaymentOperation = {
1986
+ action: "manual_payment";
1987
+ payerId: string;
1988
+ paidForUserId?: string | null;
1989
+ amount: number;
1990
+ method: string;
1991
+ notes?: string;
1992
+ year?: number;
1993
+ } | {
1994
+ action: "assign_fee";
1995
+ memberId: string;
1996
+ feeTierId: string;
1997
+ feeType: "base" | "addon";
1998
+ } | {
1999
+ action: "refund";
2000
+ paymentId: string;
2001
+ } | {
2002
+ action: "link_refund";
2003
+ refundEventId: string;
2004
+ paymentId: string;
2005
+ } | {
2006
+ action: "nudge";
2007
+ memberIds: string[];
2008
+ };
2009
+ interface AdminPaymentOperationResult {
2010
+ success: true;
2011
+ paymentId?: string;
2012
+ sent?: number;
2013
+ failed?: number;
2014
+ }
2015
+ interface AdminPaymentSummary {
2016
+ totalUsers: number;
2017
+ totalOwed: number;
2018
+ totalPaid: number;
2019
+ totalBalance: number;
2020
+ paidCount: number;
2021
+ partialCount: number;
2022
+ unpaidCount: number;
2023
+ }
2024
+ interface UnmatchedRefund {
2025
+ id: string;
2026
+ amount: string;
2027
+ method: string | null;
2028
+ reason: string | null;
2029
+ refundedAt: string;
2030
+ givebutterRefundId: string;
2031
+ }
2032
+ interface SchedulingAvailability {
2033
+ id: string;
2034
+ dayOfWeek: number;
2035
+ startTime: string;
2036
+ endTime: string;
2037
+ timezone: string;
2038
+ }
2039
+ interface SchedulingOverride {
2040
+ id: string;
2041
+ overrideDate: string;
2042
+ overrideType: string;
2043
+ startTime: string | null;
2044
+ endTime: string | null;
2045
+ reason: string | null;
2046
+ }
2047
+ interface SchedulingAdminResult {
2048
+ token?: string;
2049
+ interviewerId?: string;
2050
+ availability?: SchedulingAvailability;
2051
+ override?: SchedulingOverride;
2052
+ success?: boolean;
2053
+ }
2054
+ interface SchedulingAdminSettings {
2055
+ googleConnected: boolean;
2056
+ interviewer: {
2057
+ id: string;
2058
+ schedulingType: string | null;
2059
+ externalSchedulingUrl: string | null;
2060
+ } | null;
2061
+ availability: SchedulingAvailability[];
2062
+ overrides: SchedulingOverride[];
2063
+ bookings: {
2064
+ id: string;
2065
+ candidateName: string;
2066
+ candidateEmail: string;
2067
+ startsAt: string;
2068
+ endsAt: string;
2069
+ applicationId: string;
2070
+ }[];
2071
+ }
2072
+ type SchedulingAdminOperation = {
2073
+ action: "feed_settings" | "rotate_feed";
2074
+ } | {
2075
+ action: "add_availability";
2076
+ interviewerId: string;
2077
+ input: {
2078
+ dayOfWeek: number;
2079
+ startTime: string;
2080
+ endTime: string;
2081
+ timezone: string;
2082
+ };
2083
+ } | {
2084
+ action: "delete_availability" | "delete_override";
2085
+ id: string;
2086
+ } | {
2087
+ action: "add_override";
2088
+ interviewerId: string;
2089
+ input: {
2090
+ overrideDate: string;
2091
+ overrideType: "block" | "available";
2092
+ startTime: string | null;
2093
+ endTime: string | null;
2094
+ };
2095
+ } | {
2096
+ action: "set_type";
2097
+ schedulingType: "google" | "external" | "manual";
2098
+ externalUrl?: string;
2099
+ };
2100
+ interface InterviewFeedBooking {
2101
+ id: string;
2102
+ startsAt: string;
2103
+ endsAt: string;
2104
+ candidateName: string;
2105
+ candidateEmail: string;
2106
+ candidateTimezone: string;
2107
+ applicationId: string;
2108
+ interviewerName: string | null;
2109
+ }
2110
+ interface AdminImportantDate {
2111
+ id: string;
2112
+ title: string;
2113
+ description: string | null;
2114
+ date: string;
2115
+ endDate: string | null;
2116
+ category: string | null;
2117
+ notifyDaysBefore: number[] | null;
2118
+ isSystem: boolean | null;
2119
+ slug: string | null;
2120
+ }
2121
+ interface AdminImportantDateInput {
2122
+ title: string;
2123
+ description: string;
2124
+ date: string;
2125
+ endDate: string | null;
2126
+ category: "dues" | "documents" | "tickets" | "event" | "other" | "system";
2127
+ notifyDaysBefore: number[];
2128
+ }
2129
+ type AdminImportantDateOperation = {
2130
+ action: "create";
2131
+ input: AdminImportantDateInput;
2132
+ } | {
2133
+ action: "update";
2134
+ id: string;
2135
+ input: AdminImportantDateInput;
2136
+ } | {
2137
+ action: "delete";
2138
+ id: string;
2139
+ };
2140
+ interface AdminPaymentsPage {
2141
+ year: number;
2142
+ transactions: {
2143
+ id: string;
2144
+ userId: string | null;
2145
+ date: string | null;
2146
+ createdAt: string | null;
2147
+ memberName: string;
2148
+ memberEmail: string;
2149
+ description: string | null;
2150
+ duesType: string | null;
2151
+ amount: number;
2152
+ paymentMethod: string;
2153
+ status: string;
2154
+ paidByName: string | null;
2155
+ paymentId: string | null;
2156
+ }[];
2157
+ typeBreakdown: {
2158
+ duesType: string | null;
2159
+ type: string;
2160
+ count: number;
2161
+ total: number;
2162
+ }[];
2163
+ unmatchedRefunds: {
2164
+ id: string;
2165
+ amount: string;
2166
+ method: string | null;
2167
+ reason: string | null;
2168
+ refundedAt: string;
2169
+ givebutterRefundId: string;
2170
+ }[];
2171
+ membersForPayment: {
2172
+ id: string;
2173
+ name: string;
2174
+ email: string;
2175
+ balance: number;
2176
+ }[];
2177
+ membersForRefund: {
2178
+ id: string;
2179
+ name: string;
2180
+ email: string;
2181
+ }[];
2182
+ }
2183
+ interface ScholarshipStats {
2184
+ totalAssigned: number;
2185
+ totalUsed: number;
2186
+ totalExpired: number;
2187
+ totalAmount: number;
2188
+ usedAmount: number;
2189
+ }
2190
+ interface AdminScholarshipsPage {
2191
+ year: number;
2192
+ scholarships: {
2193
+ id: string;
2194
+ userId: string;
2195
+ promoCode: string;
2196
+ discountAmount: string;
2197
+ reason: string | null;
2198
+ status: ScholarshipStatus;
2199
+ year: number;
2200
+ usedAt: string | null;
2201
+ createdAt: string | null;
2202
+ profile: {
2203
+ id: string;
2204
+ name: string | null;
2205
+ email: string | null;
2206
+ } | null;
2207
+ }[];
2208
+ availableMembers: {
2209
+ id: string;
2210
+ name: string | null;
2211
+ email: string | null;
2212
+ }[];
2213
+ usersWithSucceededPayment: string[];
2214
+ paymentLookupErrorMessage: string | null;
2215
+ discountsApplied: {
2216
+ id: string;
2217
+ discount: string | null;
2218
+ description: string | null;
2219
+ createdAt: string | null;
2220
+ profile: {
2221
+ id: string;
2222
+ name: string | null;
2223
+ email: string | null;
2224
+ } | null;
2225
+ }[];
2226
+ stats: ScholarshipStats;
2227
+ }
2228
+ type AdminMemberRole = "applicant" | "member" | "admin" | "super_admin";
2229
+ type AdminMemberStatus = "registered" | "pending" | "invite_sent" | "interview_scheduled" | "interviewed" | "approved" | "waitlisted" | "active" | "rejected" | "inactive";
2230
+ interface AdminMemberInvite {
2231
+ firstName: string;
2232
+ lastName: string;
2233
+ email: string;
2234
+ phone?: string | null;
2235
+ role: AdminMemberRole;
2236
+ status: AdminMemberStatus;
2237
+ virginBurner?: boolean;
2238
+ sendInvite?: boolean;
2239
+ }
2240
+ type AdminMemberOperation = {
2241
+ action: "role";
2242
+ profileId: string;
2243
+ role: AdminMemberRole;
2244
+ } | {
2245
+ action: "admin_roles";
2246
+ profileId: string;
2247
+ adminRoles: ("super_admin" | "finance" | "operations" | "membership" | "scholarship")[];
2248
+ } | {
2249
+ action: "status";
2250
+ profileId: string;
2251
+ status: AdminMemberStatus;
2252
+ } | {
2253
+ action: "attendance";
2254
+ profileId: string;
2255
+ attendanceResponse: "attending" | "not_attending" | "undecided" | null;
2256
+ /** Defaults to the active camp year. An explicit year must already have a camp year row. */
2257
+ year?: number;
2258
+ } | {
2259
+ action: "profile";
2260
+ profileId: string;
2261
+ profile?: MemberProfileUpdate;
2262
+ campYear?: Omit<MemberTravelUpdate, "attendanceResponse">;
2263
+ year?: number;
2264
+ } | {
2265
+ action: "delete";
2266
+ profileId: string;
2267
+ } | ({
2268
+ action: "invite";
2269
+ } & AdminMemberInvite) | {
2270
+ action: "bike_interest";
2271
+ profileId: string;
2272
+ wantsBikeRental: boolean;
2273
+ bikeTypePreference: "ebike" | "pedal" | null;
2274
+ /** Defaults to the active camp year. An explicit year must already have a camp year row. */
2275
+ year?: number;
2276
+ } | {
2277
+ action: "summer_rsvp";
2278
+ profileId: string;
2279
+ eventId: string;
2280
+ nightsAttending: string[];
2281
+ isDayTripOnly: boolean;
2282
+ dietaryRestrictions: string | null;
2283
+ notes: string | null;
2284
+ } | {
2285
+ action: "summer_cancel";
2286
+ rsvpId: string;
2287
+ } | {
2288
+ action: "meeting_rsvp";
2289
+ profileId: string;
2290
+ meetingId: string;
2291
+ dateOptionId: string;
2292
+ } | {
2293
+ action: "meeting_cancel";
2294
+ profileId: string;
2295
+ meetingId: string;
2296
+ };
2297
+ interface AdminImportRow {
2298
+ firstName: string;
2299
+ lastName: string;
2300
+ name?: string;
2301
+ email: string;
2302
+ phone?: string | null;
2303
+ playaName?: string | null;
2304
+ yearJoined?: number | null;
2305
+ attendingThisYear?: boolean;
2306
+ role: AdminMemberRole;
2307
+ status: AdminMemberStatus;
2308
+ }
2309
+ type AdminImportOperation = {
2310
+ action: "validate_emails";
2311
+ emails: string[];
2312
+ } | {
2313
+ action: "import";
2314
+ rows: AdminImportRow[];
2315
+ year: number;
2316
+ } | {
2317
+ action: "welcome";
2318
+ profileIds: string[];
2319
+ } | {
2320
+ action: "invite_broadcast";
2321
+ } | {
2322
+ action: "invite_existing";
2323
+ profileId: string;
2324
+ };
2325
+ interface AdminImportResult {
2326
+ duplicates?: string[];
2327
+ created?: number;
2328
+ failed?: number;
2329
+ errors?: string[];
2330
+ createdRows?: {
2331
+ index: number;
2332
+ profileId: string;
2333
+ }[];
2334
+ sent?: number;
2335
+ skipped?: number;
2336
+ }
2337
+ type BookkeepingAdminOperation = {
2338
+ action: "close" | "rollover";
2339
+ year: number;
2340
+ } | {
2341
+ action: "lessons";
2342
+ year: number;
2343
+ text: string;
2344
+ };
2345
+ interface AdminGivebutterWidgets {
2346
+ year: number;
2347
+ widgets: {
2348
+ id: string;
2349
+ category: string;
2350
+ tierKey: string;
2351
+ widgetId: string;
2352
+ label: string | null;
2353
+ isActive: boolean;
2354
+ year: number;
2355
+ }[];
2356
+ }
2357
+ type AdminGivebutterWidgetOperation = {
2358
+ action: "upsert";
2359
+ category: "dues" | "rv_addon" | "donation";
2360
+ tierKey: string;
2361
+ widgetId: string;
2362
+ label: string | null;
2363
+ } | {
2364
+ action: "delete";
2365
+ id: string;
2366
+ } | {
2367
+ action: "toggle";
2368
+ id: string;
2369
+ isActive: boolean;
2370
+ };
2371
+ type EmailSegmentKey = "allMembers" | "admins" | "unpaidDues" | "rvFeesOwed" | "hasntLoggedIn" | "outstandingRsvp" | "needsTicket" | "attendingBuildWeek" | "attendingSummerCamp" | "hasUnsignedDocuments";
2372
+ interface EmailRecipientFilter {
2373
+ status?: string[];
2374
+ paymentStatus?: string[];
2375
+ isAttending?: boolean;
2376
+ isBuildWeek?: boolean;
2377
+ tagIds?: string[];
2378
+ roles?: string[];
2379
+ memberIds?: string[];
2380
+ }
2381
+ interface EmailRecipient {
2382
+ id: string;
2383
+ name: string | null;
2384
+ email: string;
2385
+ }
2386
+ interface EmailComposerOptions {
2387
+ tags: {
2388
+ id: string;
2389
+ name: string;
2390
+ color: string;
2391
+ memberCount: number;
2392
+ }[];
2393
+ members: EmailRecipient[];
2394
+ segmentCounts: Record<EmailSegmentKey, number | null>;
2395
+ }
2396
+ /**
2397
+ * The admin delivery/retry tab. Each log is an `email_retries` row (PLA-801, the single retry
2398
+ * system). The `retried` tab lists rows re-attempted at least once.
2399
+ */
2400
+ interface EmailDeliveryPage {
2401
+ logs: {
2402
+ id: string;
2403
+ recipientEmail: string | null;
2404
+ subject: string;
2405
+ emailType: string;
2406
+ /** Always null: retry rows carry the rendered message, not a template reference. */
2407
+ templateId: string | null;
2408
+ status: string;
2409
+ error: string | null;
2410
+ /** Provider failure class (e.g. transient vs permanent) when the last attempt failed. */
2411
+ failureClass: string | null;
2412
+ retryCount: number;
2413
+ /** When the retry executor will next attempt the row, if it is still pending. */
2414
+ nextRetryAt: string | null;
2415
+ /** Set only for delivered rows. */
2416
+ sentAt: string | null;
2417
+ createdAt: string;
2418
+ updatedAt: string;
2419
+ }[];
2420
+ totalSent: number;
2421
+ succeededSent: number;
2422
+ failed: number;
2423
+ queued: number;
2424
+ retryableCount: number;
2425
+ successRate: number;
2426
+ tabCounts: {
2427
+ failed: number;
2428
+ queued: number;
2429
+ succeeded: number;
2430
+ retried: number;
2431
+ };
2432
+ tabTotal: number;
2433
+ safePage: number;
2434
+ }
2435
+ /** Result of one `emails.syncContacts` call (POST /email/contacts/sync). */
2436
+ interface ContactSyncResponse {
2437
+ /** Contacts synced by this call only. */
2438
+ synced: number;
2439
+ /** Contacts that failed in this call only. */
2440
+ failed: number;
2441
+ /** True when the call stopped at its time limit before finishing; resume with `cursor`. */
2442
+ skipped: boolean;
2443
+ /** Opaque resume token for a partial sync; null once the sync is complete. */
2444
+ cursor: string | null;
2445
+ message: string;
2446
+ }
2447
+ interface EmailCmsPreview {
2448
+ html: string;
2449
+ cmsAvailable: boolean;
2450
+ storyId: number | null;
2451
+ templateContent: {
2452
+ subject: string;
2453
+ previewText: string;
2454
+ heading: string;
2455
+ body: string;
2456
+ ctaText: string;
2457
+ ctaUrl: string;
2458
+ signOff: string;
2459
+ signOffName: string;
2460
+ } | null;
2461
+ baseContent: {
2462
+ logoImage: string;
2463
+ logoText: string;
2464
+ footerText: string;
2465
+ footerUrl: string;
2466
+ footerUrlText: string;
2467
+ noreplyText: string;
2468
+ contactEmail: string;
2469
+ };
2470
+ }
2471
+ interface AdminMemberExportRow {
2472
+ email: string;
2473
+ firstName: string | null;
2474
+ lastName: string | null;
2475
+ status: string | null;
2476
+ role: string | null;
2477
+ hasPaidBaseDues: boolean;
2478
+ hasPaidRvDues: boolean;
2479
+ ownsRvShelter: boolean;
2480
+ shelterType: string | null;
2481
+ isAttending: boolean;
2482
+ }
2483
+ interface AdminGivebutterCatalog {
2484
+ campaigns: {
2485
+ id: number;
2486
+ title: string;
2487
+ status: string;
2488
+ lastSyncedAt: string;
2489
+ }[];
2490
+ items: {
2491
+ id: number;
2492
+ campaignId: number;
2493
+ name: string;
2494
+ price: number;
2495
+ active: boolean;
2496
+ }[];
2497
+ activeTier: {
2498
+ tier: "base_dues";
2499
+ campaignId: number;
2500
+ itemId: number;
2501
+ } | null;
2502
+ }
2503
+ type AdminGivebutterCatalogOperation = {
2504
+ action: "sync";
2505
+ } | {
2506
+ action: "set_active_tier";
2507
+ tier: "base_dues";
2508
+ campaignId: number;
2509
+ itemId: number;
2510
+ };
2511
+ //#endregion
2512
+ //#region src/client.d.ts
2513
+ interface ClientOptions {
2514
+ /** Base URL for authenticated /api/v1 routes, e.g. https://api.playaos.app */
2515
+ baseUrl: string;
2516
+ /** Optional base URL for /api/embed/v1 routes when they live on a different host. */
2517
+ embedBaseUrl?: string;
2518
+ /** API key in the format pk_live_* */
2519
+ apiKey: string;
2520
+ /**
2521
+ * Supabase session JWT of the acting member, sent as `X-PlayaOS-Member-Token`
2522
+ * on every /api/v1 call (PLA-1195). Member-scoped endpoints (a member's own
2523
+ * dues, payments, application, shelter, shifts signup, …) require it and
2524
+ * return 401 without it. Org-level endpoints do not require it, but a token
2525
+ * that is sent must still verify — an expired or invalid one is a 401 on any
2526
+ * /api/v1 route that installs the member middleware. Prefer
2527
+ * `client.withMember(token)` to derive a per-request client from a shared
2528
+ * server-side one rather than constructing a client per user.
2529
+ */
2530
+ memberToken?: string;
2531
+ }
2532
+ export declare class PlayaOSClient {
2533
+ private readonly baseUrl;
2534
+ private readonly embedBaseUrl;
2535
+ private readonly apiKey;
2536
+ private readonly memberToken;
2537
+ constructor(opts: ClientOptions);
2538
+ /** Credentials for /api/v1 calls; the embed surface uses `apiKey` alone as the camp key. */
2539
+ private get auth();
2540
+ /**
2541
+ * Derive a client that acts as one member (PLA-1195): same host and org key,
2542
+ * plus the member's Supabase session JWT on every /api/v1 call. Use this in a
2543
+ * server that holds one org key and serves many signed-in members.
2544
+ */
2545
+ withMember(memberToken: string): PlayaOSClient;
2546
+ /**
2547
+ * Admin dual-path (PLA-1203): when the client has a memberToken, call `/api/v1`
2548
+ * (org key + X-PlayaOS-Member-Token). Otherwise keep the legacy embed-admin
2549
+ * Bearer-JWT path so published consumers without withMember() still work.
2550
+ */
2551
+ private adminV1OrEmbed;
2552
+ /** Resolve admin credential: memberToken clients skip accessToken; embed path requires it. */
2553
+ private adminAccess;
2554
+ readonly publicBooking: {
2555
+ details: (token: string, opts?: {
2556
+ signal?: AbortSignal;
2557
+ }) => Promise<{
2558
+ title: string;
2559
+ description: string | null;
2560
+ durationMinutes: number;
2561
+ candidateName: string;
2562
+ candidateEmail: string;
2563
+ booking: {
2564
+ id: string;
2565
+ startsAt: string;
2566
+ endsAt: string;
2567
+ timezone: string;
2568
+ } | null;
2569
+ }>;
2570
+ slots: (token: string, opts?: {
2571
+ signal?: AbortSignal;
2572
+ }) => Promise<{
2573
+ slots: Array<{
2574
+ start: string;
2575
+ end: string;
2576
+ interviewerId: string;
2577
+ }>;
2578
+ }>;
2579
+ book: (token: string, payload: {
2580
+ slotStart: string;
2581
+ interviewerId: string;
2582
+ candidateTimezone: string;
2583
+ }, opts?: {
2584
+ signal?: AbortSignal;
2585
+ }) => Promise<{
2586
+ booking: {
2587
+ id: string;
2588
+ startsAt: string;
2589
+ endsAt: string;
2590
+ meetLink: string | null;
2591
+ };
2592
+ }>;
2593
+ cancel: (token: string, payload: {
2594
+ bookingId: string;
2595
+ }, opts?: {
2596
+ signal?: AbortSignal;
2597
+ }) => Promise<{
2598
+ cancelled: true;
2599
+ }>;
2600
+ };
2601
+ readonly campSettings: {
2602
+ catalog: (opts?: {
2603
+ signal?: AbortSignal;
2604
+ }) => Promise<AdminGivebutterCatalog>;
2605
+ catalogOperation: (payload: AdminGivebutterCatalogOperation, opts?: {
2606
+ signal?: AbortSignal;
2607
+ }) => Promise<{
2608
+ success?: boolean;
2609
+ campaigns?: number;
2610
+ items?: number;
2611
+ }>;
2612
+ widgets: (opts?: {
2613
+ signal?: AbortSignal;
2614
+ }) => Promise<AdminGivebutterWidgets>;
2615
+ widgetOperation: (payload: AdminGivebutterWidgetOperation, opts?: {
2616
+ signal?: AbortSignal;
2617
+ }) => Promise<{
2618
+ success: true;
2619
+ }>;
2620
+ admin: (opts?: {
2621
+ signal?: AbortSignal;
2622
+ }) => Promise<AdminCampSettings>;
2623
+ update: (payload: CampSettingsOperation, opts?: {
2624
+ signal?: AbortSignal;
2625
+ }) => Promise<{
2626
+ success: true;
2627
+ }>;
2628
+ };
2629
+ readonly scheduling: {
2630
+ adminSettings: (opts?: {
2631
+ signal?: AbortSignal;
2632
+ }) => Promise<SchedulingAdminSettings>;
2633
+ adminOperation: (payload: SchedulingAdminOperation, opts?: {
2634
+ signal?: AbortSignal;
2635
+ }) => Promise<SchedulingAdminResult>;
2636
+ feed: (interviewerId: string, token: string, opts?: {
2637
+ signal?: AbortSignal;
2638
+ }) => Promise<InterviewFeedBooking[]>;
2639
+ };
2640
+ readonly members: {
2641
+ adminExport: (params: {
2642
+ year: number;
2643
+ }, opts?: {
2644
+ signal?: AbortSignal;
2645
+ }) => Promise<{
2646
+ data: AdminMemberExportRow[];
2647
+ }>;
2648
+ adminOperation: (payload: AdminMemberOperation, opts?: {
2649
+ signal?: AbortSignal;
2650
+ }) => Promise<{
2651
+ success: true;
2652
+ profileId?: string;
2653
+ year?: number;
2654
+ }>;
2655
+ adminImportOperation: (payload: AdminImportOperation, opts?: {
2656
+ signal?: AbortSignal;
2657
+ }) => Promise<AdminImportResult>;
2658
+ adminDetail: (id: string, params?: {
2659
+ year?: number;
2660
+ }, opts?: {
2661
+ signal?: AbortSignal;
2662
+ }) => Promise<MemberProfileDetails>;
2663
+ adminHistory: (id: string, opts?: {
2664
+ signal?: AbortSignal;
2665
+ }) => Promise<{
2666
+ data: {
2667
+ id: string;
2668
+ editorName: string | null;
2669
+ changes: Record<string, {
2670
+ from: unknown;
2671
+ to: unknown;
2672
+ }>;
2673
+ createdAt: string | null;
2674
+ }[];
2675
+ }>;
2676
+ selfProfile: (params?: {
2677
+ year?: number;
2678
+ }, opts?: {
2679
+ signal?: AbortSignal;
2680
+ }) => Promise<MemberProfileDetails>;
2681
+ updateSelfProfile: (payload: MemberSelfProfilePatch, opts?: {
2682
+ signal?: AbortSignal;
2683
+ }) => Promise<{
2684
+ profileId: string;
2685
+ year: number | null;
2686
+ }>;
2687
+ referrers: (params: {
2688
+ q: string;
2689
+ }, opts?: {
2690
+ signal?: AbortSignal;
2691
+ }) => Promise<{
2692
+ data: Array<{
2693
+ id: string;
2694
+ name: string | null;
2695
+ }>;
2696
+ }>;
2697
+ referrer: (id: string, opts?: {
2698
+ signal?: AbortSignal;
2699
+ }) => Promise<{
2700
+ id: string;
2701
+ name: string | null;
2702
+ }>;
2703
+ getPushPreferences: (opts?: {
2704
+ signal?: AbortSignal;
2705
+ }) => Promise<MemberPushPreferences>;
2706
+ updatePushPreferences: (payload: Partial<MemberPushPreferences>, opts?: {
2707
+ signal?: AbortSignal;
2708
+ }) => Promise<MemberPushPreferences>;
2709
+ adminPhotoDownloadUrl: (id: string, params?: {
2710
+ original?: boolean;
2711
+ }, opts?: {
2712
+ signal?: AbortSignal;
2713
+ }) => Promise<{
2714
+ url: string;
2715
+ fileName: string;
2716
+ }>;
2717
+ adminPhotoUploadUrl: (id: string, payload: {
2718
+ contentType: "image/jpeg" | "image/png" | "image/webp";
2719
+ kind?: "avatar" | "original";
2720
+ }, opts?: {
2721
+ signal?: AbortSignal;
2722
+ }) => Promise<{
2723
+ uploadUrl: string;
2724
+ path: string;
2725
+ token: string;
2726
+ key: string;
2727
+ }>;
2728
+ adminSetPhoto: (id: string, payload: {
2729
+ key: string;
2730
+ originalKey?: string | null;
2731
+ }, opts?: {
2732
+ signal?: AbortSignal;
2733
+ }) => Promise<{
2734
+ avatarUrl: string;
2735
+ originalUrl: string | null;
2736
+ }>;
2737
+ adminDeletePhoto: (id: string, opts?: {
2738
+ signal?: AbortSignal;
2739
+ }) => Promise<{
2740
+ success: boolean;
2741
+ }>;
2742
+ updateOnboarding: (payload: MemberOnboardingUpdate, opts?: {
2743
+ signal?: AbortSignal;
2744
+ }) => Promise<{
2745
+ profileId: string;
2746
+ year: number | null;
2747
+ }>;
2748
+ bootstrap: (opts?: {
2749
+ signal?: AbortSignal;
2750
+ }) => Promise<MemberBootstrap>;
2751
+ dashboard: (opts?: {
2752
+ signal?: AbortSignal;
2753
+ }) => Promise<MemberDashboard>;
2754
+ /** Presigned profile-photo upload (PLA-1263). PUT the bytes, then setPhoto. */
2755
+ createPhotoUploadUrl: (payload: {
2756
+ contentType: "image/jpeg" | "image/png" | "image/webp";
2757
+ kind?: "avatar" | "original";
2758
+ }, opts?: {
2759
+ signal?: AbortSignal;
2760
+ }) => Promise<{
2761
+ uploadUrl: string;
2762
+ path: string;
2763
+ token: string;
2764
+ key: string;
2765
+ }>;
2766
+ setPhoto: (payload: {
2767
+ key: string;
2768
+ originalKey?: string | null;
2769
+ }, opts?: {
2770
+ signal?: AbortSignal;
2771
+ }) => Promise<{
2772
+ avatarUrl: string;
2773
+ originalUrl: string | null;
2774
+ }>;
2775
+ deletePhoto: (opts?: {
2776
+ signal?: AbortSignal;
2777
+ }) => Promise<{
2778
+ success: boolean;
2779
+ }>;
2780
+ /** Active push device tokens for the acting member (PLA-1261). */
2781
+ listDevices: (opts?: {
2782
+ signal?: AbortSignal;
2783
+ }) => Promise<MemberDevice[]>;
2784
+ registerDevice: (payload: {
2785
+ token: string;
2786
+ platform: "ios" | "android";
2787
+ environment?: "sandbox" | "production";
2788
+ }, opts?: {
2789
+ signal?: AbortSignal;
2790
+ }) => Promise<{
2791
+ id: string;
2792
+ registered: boolean;
2793
+ }>;
2794
+ deleteDevice: (payload: {
2795
+ token: string;
2796
+ }, opts?: {
2797
+ signal?: AbortSignal;
2798
+ }) => Promise<{
2799
+ unregistered: boolean;
2800
+ }>;
2801
+ /** The acting member's communication + (admin) notification preferences (PLA-1262). */
2802
+ getPreferences: (opts?: {
2803
+ signal?: AbortSignal;
2804
+ }) => Promise<MemberPreferences>;
2805
+ updatePreferences: (payload: {
2806
+ emailMarketingOptIn?: boolean;
2807
+ adminNotifications?: Partial<AdminNotificationPrefs>;
2808
+ }, opts?: {
2809
+ signal?: AbortSignal;
2810
+ }) => Promise<MemberPreferences>;
2811
+ list: (params?: {
2812
+ role?: MemberRole;
2813
+ status?: string;
2814
+ /** Comma-separated roles; wins over `role` (e.g. `admin,member`). */
2815
+ roles?: string;
2816
+ /** Comma-separated statuses; wins over `status` (e.g. `active,inactive`). */
2817
+ statuses?: string;
2818
+ q?: string;
2819
+ sortBy?: "name" | "email" | "role" | "status" | "createdAt";
2820
+ sortOrder?: "asc" | "desc";
2821
+ attending?: "true" | "false";
2822
+ } & PaginationParams & {
2823
+ /** Raw row offset — the members table's pager. Mutually exclusive with `cursor`. */
2824
+ offset?: number;
2825
+ }, opts?: {
2826
+ signal?: AbortSignal;
2827
+ }) => Promise<MembersListResponse>;
2828
+ /**
2829
+ * Full profile (phone, emergency contact). Requires a member token; pass
2830
+ * `"me"` for the acting member — non-admins may fetch only themselves.
1474
2831
  */
1475
2832
  get: (id: string, opts?: {
1476
2833
  signal?: AbortSignal;
@@ -1529,6 +2886,7 @@ export declare class PlayaOSClient {
1529
2886
  signal?: AbortSignal;
1530
2887
  }) => Promise<{
1531
2888
  url: string;
2889
+ fileName: string;
1532
2890
  }>;
1533
2891
  };
1534
2892
  /** Summer-camp events + the acting member's RSVP (PLA-1270). */
@@ -1590,9 +2948,40 @@ export declare class PlayaOSClient {
1590
2948
  paymentStatus?: "unpaid" | "partial" | "paid";
1591
2949
  } & PaginationParams, opts?: {
1592
2950
  signal?: AbortSignal;
1593
- }) => Promise<Paginated<DuesStatus>>;
1594
- };
1595
- readonly shifts: {
2951
+ }) => Promise<Paginated<DuesStatus>>;
2952
+ };
2953
+ readonly shifts: {
2954
+ memberAction: (payload: {
2955
+ action: "signup";
2956
+ shiftId: string;
2957
+ } | {
2958
+ action: "cancel";
2959
+ signupId: string;
2960
+ }, opts?: {
2961
+ signal?: AbortSignal;
2962
+ }) => Promise<{
2963
+ success: true;
2964
+ }>;
2965
+ mobile: (params: {
2966
+ type: "available" | "my-shifts";
2967
+ date: string;
2968
+ }, opts?: {
2969
+ signal?: AbortSignal;
2970
+ }) => Promise<MobileShifts>;
2971
+ memberView: (opts?: {
2972
+ signal?: AbortSignal;
2973
+ }) => Promise<MemberShiftView>;
2974
+ adminWorkflow: (payload: ShiftAdminWorkflow, opts?: {
2975
+ signal?: AbortSignal;
2976
+ }) => Promise<ShiftAdminWorkflowResult>;
2977
+ planner: (params?: {
2978
+ year?: number;
2979
+ }, opts?: {
2980
+ signal?: AbortSignal;
2981
+ }) => Promise<ShiftPlannerData>;
2982
+ adminOperation: (payload: ShiftAdminOperation, opts?: {
2983
+ signal?: AbortSignal;
2984
+ }) => Promise<ShiftAdminOperationResult>;
1596
2985
  adminTypes: (opts?: {
1597
2986
  signal?: AbortSignal;
1598
2987
  }) => Promise<AdminShiftType[]>;
@@ -1622,6 +3011,37 @@ export declare class PlayaOSClient {
1622
3011
  }) => Promise<CommitmentsListResponse>;
1623
3012
  };
1624
3013
  readonly payments: {
3014
+ adminPage: (params?: {
3015
+ year?: number;
3016
+ }, opts?: {
3017
+ signal?: AbortSignal;
3018
+ }) => Promise<AdminPaymentsPage>;
3019
+ adminOperation: (payload: AdminPaymentOperation, opts?: {
3020
+ signal?: AbortSignal;
3021
+ }) => Promise<AdminPaymentOperationResult>;
3022
+ unmatchedRefunds: (opts?: {
3023
+ signal?: AbortSignal;
3024
+ }) => Promise<UnmatchedRefund[]>;
3025
+ memberPayments: (id: string, opts?: {
3026
+ signal?: AbortSignal;
3027
+ }) => Promise<Array<{
3028
+ id: string;
3029
+ amount: string;
3030
+ paymentStatus: string | null;
3031
+ paymentDate: string | null;
3032
+ paymentMethod: string | null;
3033
+ }>>;
3034
+ adminSummary: (opts?: {
3035
+ signal?: AbortSignal;
3036
+ }) => Promise<AdminPaymentSummary>;
3037
+ exportMonarch: (params?: {
3038
+ from?: string;
3039
+ to?: string;
3040
+ }, opts?: {
3041
+ signal?: AbortSignal;
3042
+ }) => Promise<{
3043
+ csv: string;
3044
+ }>;
1625
3045
  list: (params?: {
1626
3046
  type?: "dues" | "payment";
1627
3047
  memberId?: string;
@@ -1692,6 +3112,11 @@ export declare class PlayaOSClient {
1692
3112
  };
1693
3113
  /** Bookkeeping reads (PLA-1345): camp-year list + ops-binder export preview. */
1694
3114
  readonly bookkeeping: {
3115
+ adminOperation: (payload: BookkeepingAdminOperation, opts?: {
3116
+ signal?: AbortSignal;
3117
+ }) => Promise<{
3118
+ success: true;
3119
+ }>;
1695
3120
  years: (opts?: {
1696
3121
  signal?: AbortSignal;
1697
3122
  }) => Promise<CampYearWithCounts[]>;
@@ -1715,6 +3140,16 @@ export declare class PlayaOSClient {
1715
3140
  }) => Promise<Paginated<WebhookLog>>;
1716
3141
  };
1717
3142
  readonly notifications: {
3143
+ dispatch: (payload: {
3144
+ audience: "all" | "member" | "admin";
3145
+ title: string;
3146
+ body: string;
3147
+ }, opts?: {
3148
+ signal?: AbortSignal;
3149
+ }) => Promise<{
3150
+ queued: true;
3151
+ recipientCount: number;
3152
+ }>;
1718
3153
  /** Set the acting member's notification high-water mark to now (PLA-1261). */
1719
3154
  markSeen: (opts?: {
1720
3155
  signal?: AbortSignal;
@@ -1731,9 +3166,73 @@ export declare class PlayaOSClient {
1731
3166
  }) => Promise<NotificationLog[]>;
1732
3167
  };
1733
3168
  readonly documents: {
3169
+ memberPage: (params?: {
3170
+ year?: number;
3171
+ }, opts?: {
3172
+ signal?: AbortSignal;
3173
+ }) => Promise<MemberDocumentPage>;
3174
+ create: (payload: DocumentWriteInput, opts?: {
3175
+ signal?: AbortSignal;
3176
+ }) => Promise<CampDocument>;
3177
+ update: (id: string, payload: Partial<DocumentWriteInput>, opts?: {
3178
+ signal?: AbortSignal;
3179
+ }) => Promise<CampDocument>;
3180
+ delete: (id: string, opts?: {
3181
+ signal?: AbortSignal;
3182
+ }) => Promise<{
3183
+ id: string;
3184
+ deleted: true;
3185
+ }>;
3186
+ createUploadUrl: (payload: {
3187
+ fileName: string;
3188
+ contentType: string;
3189
+ }, opts?: {
3190
+ signal?: AbortSignal;
3191
+ }) => Promise<{
3192
+ uploadUrl: string;
3193
+ path: string;
3194
+ token: string;
3195
+ key: string;
3196
+ }>;
3197
+ sourceDownloadUrl: (payload: {
3198
+ filePath: string;
3199
+ download?: boolean;
3200
+ }, opts?: {
3201
+ signal?: AbortSignal;
3202
+ }) => Promise<{
3203
+ url: string;
3204
+ }>;
3205
+ getSections: (id: string, opts?: {
3206
+ signal?: AbortSignal;
3207
+ }) => Promise<ContractSection[]>;
3208
+ saveSections: (id: string, payload: {
3209
+ sections: Array<Omit<ContractSection, "id"> & {
3210
+ id?: string;
3211
+ }>;
3212
+ }, opts?: {
3213
+ signal?: AbortSignal;
3214
+ }) => Promise<ContractSection[]>;
3215
+ renderContract: (id: string, opts?: {
3216
+ signal?: AbortSignal;
3217
+ }) => Promise<{
3218
+ html: string;
3219
+ }>;
3220
+ signatureDownloadUrl: (id: string, opts?: {
3221
+ signal?: AbortSignal;
3222
+ }) => Promise<{
3223
+ url: string;
3224
+ fileName: string;
3225
+ }>;
3226
+ deleteSignature: (id: string, opts?: {
3227
+ signal?: AbortSignal;
3228
+ }) => Promise<{
3229
+ id: string;
3230
+ deleted: true;
3231
+ }>;
1734
3232
  list: (params?: {
1735
3233
  type?: string;
1736
3234
  year?: number;
3235
+ activeYear?: boolean;
1737
3236
  }, opts?: {
1738
3237
  signal?: AbortSignal;
1739
3238
  }) => Promise<AdminCampDocument[]>;
@@ -1753,6 +3252,11 @@ export declare class PlayaOSClient {
1753
3252
  type: "checkbox" | "drawn" | "typed";
1754
3253
  signerName?: string;
1755
3254
  };
3255
+ strict?: boolean;
3256
+ audit?: {
3257
+ ipAddress?: string;
3258
+ userAgent?: string;
3259
+ };
1756
3260
  }, opts?: {
1757
3261
  signal?: AbortSignal;
1758
3262
  }) => Promise<CampDocumentSignature>;
@@ -1762,6 +3266,19 @@ export declare class PlayaOSClient {
1762
3266
  }) => Promise<CampDocumentDownloadUrl>;
1763
3267
  };
1764
3268
  readonly meetings: {
3269
+ /** Save the acting member's response; the date option must belong to this meeting. */
3270
+ rsvp: (id: string, payload: {
3271
+ dateOptionId: string;
3272
+ }, opts?: {
3273
+ signal?: AbortSignal;
3274
+ }) => Promise<{
3275
+ ok: true;
3276
+ }>;
3277
+ cancelRsvp: (id: string, opts?: {
3278
+ signal?: AbortSignal;
3279
+ }) => Promise<{
3280
+ ok: true;
3281
+ }>;
1765
3282
  list: (params?: {
1766
3283
  year?: number;
1767
3284
  limit?: number;
@@ -1785,6 +3302,22 @@ export declare class PlayaOSClient {
1785
3302
  }>;
1786
3303
  };
1787
3304
  readonly scholarships: {
3305
+ adminPage: (params?: {
3306
+ year?: number;
3307
+ }, opts?: {
3308
+ signal?: AbortSignal;
3309
+ }) => Promise<AdminScholarshipsPage>;
3310
+ refresh: (id: string, opts?: {
3311
+ signal?: AbortSignal;
3312
+ }) => Promise<{
3313
+ givebutterActive: boolean;
3314
+ givebutterUsed: number;
3315
+ }>;
3316
+ stats: (params?: {
3317
+ year?: number;
3318
+ }, opts?: {
3319
+ signal?: AbortSignal;
3320
+ }) => Promise<ScholarshipStats>;
1788
3321
  /** Create a scholarship (code + Givebutter sync). Admin-only (PLA-1266). */
1789
3322
  create: (payload: CreateScholarshipInput, opts?: {
1790
3323
  signal?: AbortSignal;
@@ -1792,16 +3325,23 @@ export declare class PlayaOSClient {
1792
3325
  /** Move a scholarship between assigned/used/expired. Admin-only (PLA-1266). */
1793
3326
  updateStatus: (id: string, status: ScholarshipStatus, opts?: {
1794
3327
  signal?: AbortSignal;
3328
+ verifyProvider?: boolean;
3329
+ providerManaged?: boolean;
1795
3330
  }) => Promise<Scholarship>;
1796
3331
  /** Delete a scholarship (deactivates its code). Admin-only (PLA-1266). */
1797
3332
  remove: (id: string, opts?: {
1798
3333
  signal?: AbortSignal;
3334
+ providerManaged?: boolean;
1799
3335
  }) => Promise<{
1800
3336
  id: string;
1801
3337
  deleted: boolean;
1802
3338
  }>;
1803
3339
  };
1804
3340
  readonly tickets: {
3341
+ /** Admin upsert by member and camp year, including members with no existing tracking row. */
3342
+ upsert: (memberId: string, year: number, payload: TicketUpdateInput, opts?: {
3343
+ signal?: AbortSignal;
3344
+ }) => Promise<Ticket>;
1805
3345
  /** Admin ticket-page projection; requires ticket, vehicle-pass, and member read scopes. */
1806
3346
  adminList: (params?: {
1807
3347
  year?: number;
@@ -1814,12 +3354,117 @@ export declare class PlayaOSClient {
1814
3354
  }) => Promise<Ticket>;
1815
3355
  };
1816
3356
  readonly vehiclePasses: {
3357
+ /** Admin upsert by member and camp year, including members with no existing tracking row. */
3358
+ upsert: (memberId: string, year: number, payload: VehiclePassUpdateInput, opts?: {
3359
+ signal?: AbortSignal;
3360
+ }) => Promise<VehiclePass>;
1817
3361
  /** Update a member's vehicle-pass status. Admin-only (PLA-1266). */
1818
3362
  update: (id: string, payload: VehiclePassUpdateInput, opts?: {
1819
3363
  signal?: AbortSignal;
1820
3364
  }) => Promise<VehiclePass>;
1821
3365
  };
1822
3366
  readonly shelters: {
3367
+ adminOperation: (payload: AdminShelterOperation, opts?: {
3368
+ signal?: AbortSignal;
3369
+ }) => Promise<{
3370
+ success: true;
3371
+ shelterId?: string;
3372
+ feesRecalculated?: boolean;
3373
+ }>;
3374
+ createForMember: (payload: OwnerShelterCreate, opts?: {
3375
+ signal?: AbortSignal;
3376
+ }) => Promise<{
3377
+ shelterId: string;
3378
+ shareUrl: string | null;
3379
+ }>;
3380
+ updateForMember: (id: string, payload: OwnerShelterPatch, opts?: {
3381
+ signal?: AbortSignal;
3382
+ }) => Promise<{
3383
+ updated: true;
3384
+ }>;
3385
+ deleteForMember: (id: string, opts?: {
3386
+ signal?: AbortSignal;
3387
+ }) => Promise<{
3388
+ shelterType: string;
3389
+ }>;
3390
+ memberPage: (params?: {
3391
+ year?: number;
3392
+ }, opts?: {
3393
+ signal?: AbortSignal;
3394
+ }) => Promise<MemberShelterPage>;
3395
+ searchMembers: (params: {
3396
+ q: string;
3397
+ }, opts?: {
3398
+ signal?: AbortSignal;
3399
+ }) => Promise<{
3400
+ data: Array<{
3401
+ id: string;
3402
+ name: string | null;
3403
+ }>;
3404
+ }>;
3405
+ requestJoin: (id: string, opts?: {
3406
+ signal?: AbortSignal;
3407
+ }) => Promise<{
3408
+ id: string;
3409
+ }>;
3410
+ inviteCandidates: (id: string, opts?: {
3411
+ signal?: AbortSignal;
3412
+ }) => Promise<{
3413
+ data: Array<{
3414
+ id: string;
3415
+ firstName: string | null;
3416
+ lastName: string | null;
3417
+ name: string | null;
3418
+ email: string | null;
3419
+ profilePhotoPath: string | null;
3420
+ }>;
3421
+ }>;
3422
+ previewJoinRequest: (token: string, opts?: {
3423
+ signal?: AbortSignal;
3424
+ }) => Promise<{
3425
+ shelterName: string | null;
3426
+ requesterName: string | null;
3427
+ status: string | null;
3428
+ }>;
3429
+ decideJoinRequest: (payload: {
3430
+ token: string;
3431
+ approved: boolean;
3432
+ }, opts?: {
3433
+ signal?: AbortSignal;
3434
+ }) => Promise<{
3435
+ success: true;
3436
+ status: "confirmed" | "declined";
3437
+ }>;
3438
+ requestPayer: (payload: {
3439
+ payerUserId: string;
3440
+ year?: number;
3441
+ }, opts?: {
3442
+ signal?: AbortSignal;
3443
+ }) => Promise<{
3444
+ existingShelterId: string | null;
3445
+ }>;
3446
+ pendingPayerRequests: (params?: {
3447
+ year?: number;
3448
+ }, opts?: {
3449
+ signal?: AbortSignal;
3450
+ }) => Promise<{
3451
+ data: Array<{
3452
+ assignmentId: string;
3453
+ userId: string;
3454
+ name: string;
3455
+ }>;
3456
+ }>;
3457
+ resolvePayerRequests: (payload: {
3458
+ shelterId: string;
3459
+ decisions: Array<{
3460
+ assignmentId: string;
3461
+ approved: boolean;
3462
+ }>;
3463
+ }, opts?: {
3464
+ signal?: AbortSignal;
3465
+ }) => Promise<{
3466
+ success: true;
3467
+ }>;
1823
3468
  /** Admin-only shelter table/map projection; requires members:read and a member token. */
1824
3469
  adminList: (params: {
1825
3470
  year: number;
@@ -1864,6 +3509,25 @@ export declare class PlayaOSClient {
1864
3509
  }>;
1865
3510
  };
1866
3511
  readonly bikes: {
3512
+ adminOperation: (payload: AdminBikeOperation, opts?: {
3513
+ signal?: AbortSignal;
3514
+ }) => Promise<AdminBikeOperationResult>;
3515
+ memberStatus: (params?: {
3516
+ year?: number;
3517
+ }, opts?: {
3518
+ signal?: AbortSignal;
3519
+ }) => Promise<MemberBikeStatus>;
3520
+ reserveForMember: (payload: {
3521
+ bikeTypeId: string;
3522
+ year?: number;
3523
+ }, opts?: {
3524
+ signal?: AbortSignal;
3525
+ }) => Promise<{
3526
+ id: string;
3527
+ status: string;
3528
+ depositAmount: number | null;
3529
+ waiverSigned: boolean;
3530
+ }>;
1867
3531
  list: (params?: {
1868
3532
  status?: string;
1869
3533
  }, opts?: {
@@ -1933,6 +3597,37 @@ export declare class PlayaOSClient {
1933
3597
  }) => Promise<BikeRentalInterestedNotReservedResponse>;
1934
3598
  };
1935
3599
  readonly tags: {
3600
+ create: (payload: {
3601
+ name: string;
3602
+ description?: string | null;
3603
+ color?: string | null;
3604
+ }, opts?: {
3605
+ signal?: AbortSignal;
3606
+ }) => Promise<MemberTag>;
3607
+ update: (id: string, payload: {
3608
+ name: string;
3609
+ description?: string | null;
3610
+ color?: string | null;
3611
+ }, opts?: {
3612
+ signal?: AbortSignal;
3613
+ }) => Promise<MemberTag>;
3614
+ delete: (id: string, opts?: {
3615
+ signal?: AbortSignal;
3616
+ }) => Promise<{
3617
+ id: string;
3618
+ }>;
3619
+ assign: (memberId: string, tagId: string, opts?: {
3620
+ signal?: AbortSignal;
3621
+ }) => Promise<{
3622
+ memberId: string;
3623
+ tagId: string;
3624
+ }>;
3625
+ remove: (memberId: string, tagId: string, opts?: {
3626
+ signal?: AbortSignal;
3627
+ }) => Promise<{
3628
+ memberId: string;
3629
+ tagId: string;
3630
+ }>;
1936
3631
  list: (opts?: {
1937
3632
  signal?: AbortSignal;
1938
3633
  }) => Promise<MemberTagWithMemberCount[]>;
@@ -2062,12 +3757,24 @@ export declare class PlayaOSClient {
2062
3757
  /**
2063
3758
  * SAP — Special Access Pass, for early/overnight vehicle arrival (PLA-1202).
2064
3759
  * Admin/super_admin only; there is no member-facing SAP surface. Year is
2065
- * always the org's active camp year — the server derives it, callers never
2066
- * pass one.
3760
+ * the selected year when supplied, otherwise the org's active camp year.
2067
3761
  */
2068
3762
  readonly sap: {
3763
+ roster: (params?: {
3764
+ year?: number;
3765
+ }, opts?: {
3766
+ signal?: AbortSignal;
3767
+ }) => Promise<Array<{
3768
+ id: string;
3769
+ name: string | null;
3770
+ email: string | null;
3771
+ role: string | null;
3772
+ status: string | null;
3773
+ buildArrivalDate: string | null;
3774
+ }>>;
2069
3775
  allocation: {
2070
3776
  get: (opts?: {
3777
+ year?: number;
2071
3778
  signal?: AbortSignal;
2072
3779
  }) => Promise<SapAllocation>;
2073
3780
  update: (payload: UpdateSapAllocationInput, opts?: {
@@ -2075,7 +3782,21 @@ export declare class PlayaOSClient {
2075
3782
  }) => Promise<SapAllocation>;
2076
3783
  };
2077
3784
  dayAllocations: {
3785
+ update: (id: string, payload: {
3786
+ slotsAvailable: number;
3787
+ notes?: string | null;
3788
+ }, opts?: {
3789
+ signal?: AbortSignal;
3790
+ }) => Promise<{
3791
+ ok: true;
3792
+ }>;
3793
+ remove: (id: string, opts?: {
3794
+ signal?: AbortSignal;
3795
+ }) => Promise<{
3796
+ ok: true;
3797
+ }>;
2078
3798
  list: (opts?: {
3799
+ year?: number;
2079
3800
  signal?: AbortSignal;
2080
3801
  }) => Promise<{
2081
3802
  items: SapDayAllocation[];
@@ -2087,6 +3808,7 @@ export declare class PlayaOSClient {
2087
3808
  };
2088
3809
  assignments: {
2089
3810
  list: (opts?: {
3811
+ year?: number;
2090
3812
  signal?: AbortSignal;
2091
3813
  }) => Promise<{
2092
3814
  items: SapAssignment[];
@@ -2105,6 +3827,14 @@ export declare class PlayaOSClient {
2105
3827
  };
2106
3828
  };
2107
3829
  readonly importantDates: {
3830
+ adminList: (opts?: {
3831
+ signal?: AbortSignal;
3832
+ }) => Promise<AdminImportantDate[]>;
3833
+ adminOperation: (payload: AdminImportantDateOperation, opts?: {
3834
+ signal?: AbortSignal;
3835
+ }) => Promise<{
3836
+ success: true;
3837
+ }>;
2108
3838
  /** Visible camp dates (PLA-1268), optionally pinned to a year. */
2109
3839
  list: (params?: {
2110
3840
  year?: number;
@@ -2113,6 +3843,103 @@ export declare class PlayaOSClient {
2113
3843
  }) => Promise<ImportantDate[]>;
2114
3844
  };
2115
3845
  readonly emails: {
3846
+ recipients: (payload: EmailRecipientFilter, opts?: {
3847
+ signal?: AbortSignal;
3848
+ }) => Promise<EmailRecipient[]>;
3849
+ composerOptions: (params?: {
3850
+ q?: string;
3851
+ }, opts?: {
3852
+ signal?: AbortSignal;
3853
+ }) => Promise<EmailComposerOptions>;
3854
+ broadcast: (payload: {
3855
+ subject: string;
3856
+ body: string;
3857
+ filter?: EmailRecipientFilter;
3858
+ segmentKey?: EmailSegmentKey;
3859
+ }, opts?: {
3860
+ signal?: AbortSignal;
3861
+ }) => Promise<{
3862
+ success: true;
3863
+ sent: number;
3864
+ failed: number;
3865
+ total: number;
3866
+ }>;
3867
+ history: (opts?: {
3868
+ signal?: AbortSignal;
3869
+ }) => Promise<{
3870
+ broadcasts: {
3871
+ id: string;
3872
+ subject: string;
3873
+ recipientCount: number | null;
3874
+ sentAt: string | null;
3875
+ senderName: string | null;
3876
+ }[];
3877
+ }>;
3878
+ deliveryPage: (params?: {
3879
+ tab?: "failed" | "queued" | "succeeded" | "retried";
3880
+ page?: number;
3881
+ }, opts?: {
3882
+ signal?: AbortSignal;
3883
+ }) => Promise<EmailDeliveryPage>;
3884
+ /**
3885
+ * Make one failed retry row due now; the retry executor sends it (nothing is sent by this call).
3886
+ * Permanent failures are refused with 400.
3887
+ */
3888
+ retryLog: (id: string, opts?: {
3889
+ signal?: AbortSignal;
3890
+ }) => Promise<{
3891
+ success: true;
3892
+ }>;
3893
+ /** Run this camp's due retry rows through the retry executor now (about 30s budget). */
3894
+ retryFailed: (opts?: {
3895
+ signal?: AbortSignal;
3896
+ }) => Promise<{
3897
+ retried: number;
3898
+ skipped: number;
3899
+ }>;
3900
+ dismissLog: (id: string, opts?: {
3901
+ signal?: AbortSignal;
3902
+ }) => Promise<{
3903
+ success: true;
3904
+ }>;
3905
+ cmsPreview: (id: string, opts?: {
3906
+ signal?: AbortSignal;
3907
+ }) => Promise<EmailCmsPreview>;
3908
+ setupContacts: (opts?: {
3909
+ signal?: AbortSignal;
3910
+ }) => Promise<{
3911
+ segmentIds: Record<string, string>;
3912
+ failedSegments: string[];
3913
+ }>;
3914
+ /**
3915
+ * Sync this camp's members into its own Resend account. Each call works for a bounded time; when
3916
+ * it stops at that limit it returns `skipped: true` and a `cursor`. Pass that cursor back as
3917
+ * `opts.cursor` to resume after the last processed member, and repeat until `cursor` is null
3918
+ * (sync complete). `synced`/`failed` count the one call. Fails with 400 until
3919
+ * {@link setupContacts} has run, or on an invalid cursor.
3920
+ */
3921
+ syncContacts: (opts?: {
3922
+ cursor?: string | null;
3923
+ signal?: AbortSignal;
3924
+ }) => Promise<ContactSyncResponse>;
3925
+ /**
3926
+ * Release an interview invitation stuck behind an uncertain or abandoned delivery claim, so the
3927
+ * next invite attempt sends again. Check the email provider first. Accepted deliveries are never
3928
+ * released.
3929
+ */
3930
+ releaseInvitationDelivery: (applicationId: string, opts?: {
3931
+ signal?: AbortSignal;
3932
+ }) => Promise<{
3933
+ released: number;
3934
+ }>;
3935
+ syncTemplates: (opts?: {
3936
+ signal?: AbortSignal;
3937
+ }) => Promise<{
3938
+ id: string;
3939
+ name: string;
3940
+ previewId: string;
3941
+ action: "created" | "updated";
3942
+ }[]>;
2116
3943
  /** Admin template registry (PLA-1265). */
2117
3944
  listTemplates: (opts?: {
2118
3945
  signal?: AbortSignal;
@@ -2134,6 +3961,23 @@ export declare class PlayaOSClient {
2134
3961
  }) => Promise<EmailRetryListResponse>;
2135
3962
  };
2136
3963
  readonly onboarding: {
3964
+ createCustomItem: (payload: {
3965
+ categoryId: string;
3966
+ name: string;
3967
+ year: number;
3968
+ }, opts?: {
3969
+ signal?: AbortSignal;
3970
+ }) => Promise<MemberCustomChecklistItem>;
3971
+ updateCustomItem: (id: string, payload: {
3972
+ completed: boolean;
3973
+ }, opts?: {
3974
+ signal?: AbortSignal;
3975
+ }) => Promise<MemberCustomChecklistItem>;
3976
+ deleteCustomItem: (id: string, opts?: {
3977
+ signal?: AbortSignal;
3978
+ }) => Promise<{
3979
+ success: true;
3980
+ }>;
2137
3981
  /** The camp's onboarding checklist template (PLA-1340 adds `priority`). */
2138
3982
  checklist: (params?: PaginationParams, opts?: {
2139
3983
  signal?: AbortSignal;
@@ -2162,6 +4006,30 @@ export declare class PlayaOSClient {
2162
4006
  };
2163
4007
  readonly admin: {
2164
4008
  applications: {
4009
+ workflow: (id: string, payload: ApplicationWorkflowInput, opts?: {
4010
+ signal?: AbortSignal;
4011
+ }) => Promise<{
4012
+ applicationId: string;
4013
+ }>;
4014
+ workflowOptions: (params?: {
4015
+ q?: string;
4016
+ excludeUserId?: string;
4017
+ }, opts?: {
4018
+ signal?: AbortSignal;
4019
+ }) => Promise<ApplicationWorkflowOptions>;
4020
+ activity: (id: string, opts?: {
4021
+ signal?: AbortSignal;
4022
+ }) => Promise<{
4023
+ data: ApplicationActivityItem[];
4024
+ }>;
4025
+ sendMessage: (id: string, payload: {
4026
+ subject: string;
4027
+ body: string;
4028
+ }, opts?: {
4029
+ signal?: AbortSignal;
4030
+ }) => Promise<{
4031
+ success: true;
4032
+ }>;
2165
4033
  /**
2166
4034
  * Admin-scoped application list (PLA-1322): the member-safe shape plus the
2167
4035
  * applicant phone, referrer name and admin-managed metadata, with the same
@@ -2518,5 +4386,5 @@ interface PublicMarketplaceClient {
2518
4386
  }
2519
4387
  export declare function createPublicMarketplaceClient(opts: PublicMarketplaceClientOptions): PublicMarketplaceClient;
2520
4388
  //#endregion
2521
- export type { AdminBikeInventory, AdminBikeRental, AdminBikeType, AdminCampDocument, AdminDocumentSignature, AdminNotificationPrefs, AdminShelter, AdminShift, AdminShiftType, AdminTicketRow, Application, ApplicationAdmin, ApplicationAnnotations, ApplicationCapacity, ApplicationCreatePayload, ApplicationCreateResponse, ApplicationNote, ApplicationScore, ApplicationStatus, ApplicationTransitionPayload, ApplicationTransitionResponse, BikeRentalCatalogItem, BikeRentalCatalogResponse, BikeRentalDeliveryMode, BikeRentalFramePreference, BikeRentalInterestedMember, BikeRentalInterestedNotReservedResponse, BikeRentalRequestInput, BikeRentalRequestResult, BikeRentalReservation, BikeRentalReservationListResponse, BikeRentalWaiver, BookkeepingExportPreview, BuildStrikeReportRow, CampDocumentDownloadUrl, CampDocumentSignature, CampDocumentSignaturesResponse, CampYearWithCounts, Commitment, CommitmentDataType, CommitmentValue, CommitmentsListResponse, CreateMeetingInput, CreateSapAssignmentInput, CreateScholarshipInput, DailyHeadcount, DashboardMetrics, DuesStatus, DuesSummaryRow, DuesTypePayor, EmailLog, EmailRetry, EmailRetryCount, EmailRetryListResponse, EmailTemplate, ExchangeParams, ExchangeResult, ImageUploadTarget, ImportantDate, ListingImage, LogisticsBreakdowns, LogisticsSummary, MarketplaceFlagReason, Meeting, MeetingDateOption, MeetingListResponse, MeetingRsvp, Member, MemberCreatePayload, MemberCreateResponse, MemberCustomChecklistItem, MemberDeactivateResponse, MemberDevice, MemberDuesStatus, MemberPreferences, MemberRole, MemberTag, MemberTagAssignment, MemberTagWithMemberCount, MemberUpdatePayload, MemberUpdateResponse, NewListingInput, OnboardingChecklistCategory, OnboardingChecklistItem, OnboardingProgress, OrgConfig, PackingCampAdminItem, PackingCampAdminList, PackingCampCategory, PackingCampCategoryInput, PackingCampItem, PackingItem, PackingItemStatus, PackingLayer, PackingListResponse, PackingPersonalItem, PaymentPageResponse, PublicMarketplaceClient, PublicMarketplaceClientOptions, RvAmperageTotal, SapAllocation, SapAssignment, SapDayAllocation, Scholarship, ScholarshipStatus, ShelterTypeDistribution, Shift, ShiftSignup, ShiftType, Ticket, TicketStatus, TicketUpdateInput, TshirtSizeTotal, UnsureDateMember, UpdateSapAllocationInput, UpdateSapAssignmentInput, UpsertPackingCampItemInput, UpsertSapDayAllocationInput, VehiclePass, VehiclePassStatus, VehiclePassUpdateInput, Waiver, WaiverContent, WaiverSection, WaiverSignPayload, WaiverSignResponse, WaiverStatus, WebhookLog };
4389
+ export type { AdminBikeInventory, AdminBikeOperation, AdminBikeOperationResult, AdminBikeRental, AdminBikeType, AdminCampDocument, AdminCampSettings, AdminDocumentSignature, AdminGivebutterCatalog, AdminGivebutterCatalogOperation, AdminGivebutterWidgetOperation, AdminGivebutterWidgets, AdminImportOperation, AdminImportResult, AdminImportRow, AdminImportantDate, AdminImportantDateInput, AdminImportantDateOperation, AdminMemberExportRow, AdminMemberInvite, AdminMemberOperation, AdminMemberRole, AdminMemberStatus, AdminNotificationPrefs, AdminPaymentOperation, AdminPaymentOperationResult, AdminPaymentSummary, AdminPaymentsPage, AdminScholarshipsPage, AdminShelter, AdminShelterOperation, AdminShift, AdminShiftType, AdminTicketRow, Application, ApplicationActivityItem, ApplicationAdmin, ApplicationAnnotations, ApplicationCapacity, ApplicationCreatePayload, ApplicationCreateResponse, ApplicationNote, ApplicationScore, ApplicationStatus, ApplicationTransitionPayload, ApplicationTransitionResponse, ApplicationWorkflowInput, ApplicationWorkflowOptions, BikeRentalCatalogItem, BikeRentalCatalogResponse, BikeRentalDeliveryMode, BikeRentalFramePreference, BikeRentalInterestedMember, BikeRentalInterestedNotReservedResponse, BikeRentalRequestInput, BikeRentalRequestResult, BikeRentalReservation, BikeRentalReservationListResponse, BikeRentalWaiver, BookkeepingAdminOperation, BookkeepingExportPreview, BuildStrikeReportRow, CampDocumentDownloadUrl, CampDocumentSignature, CampDocumentSignaturesResponse, CampSettingsOperation, CampYearWithCounts, Commitment, CommitmentDataType, CommitmentValue, CommitmentsListResponse, ContactSyncResponse, ContractSection, CreateMeetingInput, CreateSapAssignmentInput, CreateScholarshipInput, DailyHeadcount, DashboardMetrics, DocumentWriteInput, DuesStatus, DuesSummaryRow, DuesTypePayor, EmailCmsPreview, EmailComposerOptions, EmailDeliveryPage, EmailLog, EmailRecipient, EmailRecipientFilter, EmailRetry, EmailRetryCount, EmailRetryListResponse, EmailSegmentKey, EmailTemplate, ExchangeParams, ExchangeResult, ImageUploadTarget, ImportantDate, InterviewFeedBooking, ListingImage, LogisticsBreakdowns, LogisticsSummary, MarketplaceFlagReason, Meeting, MeetingDateOption, MeetingListResponse, MeetingRsvp, Member, MemberBikeStatus, MemberBootstrap, MemberCreatePayload, MemberCreateResponse, MemberCustomChecklistItem, MemberDashboard, MemberDeactivateResponse, MemberDevice, MemberDocumentPage, MemberDuesStatus, MemberOnboardingUpdate, MemberPreferences, MemberProfileDetails, MemberPushPreferences, MemberRole, MemberSelfProfile, MemberSelfProfilePatch, MemberShelter, MemberShelterPage, MemberShiftView, MemberTag, MemberTagAssignment, MemberTagWithMemberCount, MemberUpdatePayload, MemberUpdateResponse, MobileShifts, NewListingInput, OnboardingChecklistCategory, OnboardingChecklistItem, OnboardingProgress, OrgConfig, OwnerShelterCreate, OwnerShelterPatch, PackingCampAdminItem, PackingCampAdminList, PackingCampCategory, PackingCampCategoryInput, PackingCampItem, PackingItem, PackingItemStatus, PackingLayer, PackingListResponse, PackingPersonalItem, PaymentPageResponse, PublicMarketplaceClient, PublicMarketplaceClientOptions, RvAmperageTotal, SapAllocation, SapAssignment, SapDayAllocation, SchedulingAdminOperation, SchedulingAdminResult, SchedulingAdminSettings, SchedulingAvailability, SchedulingOverride, Scholarship, ScholarshipStats, ScholarshipStatus, ShelterTypeDistribution, Shift, ShiftAdminOperation, ShiftAdminOperationResult, ShiftAdminWorkflow, ShiftAdminWorkflowResult, ShiftPlannerData, ShiftSignup, ShiftType, Ticket, TicketStatus, TicketUpdateInput, TshirtSizeTotal, UnmatchedRefund, UnsureDateMember, UpdateSapAllocationInput, UpdateSapAssignmentInput, UpsertPackingCampItemInput, UpsertSapDayAllocationInput, VehiclePass, VehiclePassStatus, VehiclePassUpdateInput, Waiver, WaiverContent, WaiverSection, WaiverSignPayload, WaiverSignResponse, WaiverStatus, WebhookLog };
2522
4390
  //# sourceMappingURL=index.d.ts.map