@proveanything/smartlinks 1.6.7 → 1.7.1

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.
Files changed (41) hide show
  1. package/dist/api/attestation.d.ts +22 -0
  2. package/dist/api/attestation.js +22 -0
  3. package/dist/api/attestations.d.ts +292 -0
  4. package/dist/api/attestations.js +405 -0
  5. package/dist/api/containers.d.ts +236 -0
  6. package/dist/api/containers.js +316 -0
  7. package/dist/api/index.d.ts +2 -0
  8. package/dist/api/index.js +2 -0
  9. package/dist/api/tags.d.ts +20 -1
  10. package/dist/api/tags.js +30 -0
  11. package/dist/docs/API_SUMMARY.md +711 -9
  12. package/dist/docs/app-manifest.md +430 -0
  13. package/dist/docs/attestations.md +498 -0
  14. package/dist/docs/container-tracking.md +437 -0
  15. package/dist/docs/deep-link-discovery.md +6 -6
  16. package/dist/docs/executor.md +554 -0
  17. package/dist/docs/interactions.md +291 -0
  18. package/dist/docs/manifests.md +200 -0
  19. package/dist/docs/mpa.md +135 -0
  20. package/dist/docs/overview.md +372 -0
  21. package/dist/index.d.ts +3 -0
  22. package/dist/openapi.yaml +3110 -1323
  23. package/dist/types/appManifest.d.ts +159 -2
  24. package/dist/types/attestation.d.ts +12 -0
  25. package/dist/types/attestations.d.ts +237 -0
  26. package/dist/types/attestations.js +11 -0
  27. package/dist/types/containers.d.ts +186 -0
  28. package/dist/types/containers.js +10 -0
  29. package/dist/types/tags.d.ts +47 -3
  30. package/docs/API_SUMMARY.md +711 -9
  31. package/docs/app-manifest.md +430 -0
  32. package/docs/attestations.md +498 -0
  33. package/docs/container-tracking.md +437 -0
  34. package/docs/deep-link-discovery.md +6 -6
  35. package/docs/executor.md +554 -0
  36. package/docs/interactions.md +291 -0
  37. package/docs/manifests.md +200 -0
  38. package/docs/mpa.md +135 -0
  39. package/docs/overview.md +372 -0
  40. package/openapi.yaml +3110 -1323
  41. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  # Smartlinks API Summary
2
2
 
3
- Version: 1.6.7 | Generated: 2026-03-03T14:18:48.483Z
3
+ Version: 1.7.1 | Generated: 2026-03-03T15:26:20.065Z
4
4
 
5
5
  This is a concise summary of all available API functions and types.
6
6
 
@@ -8,9 +8,13 @@ This is a concise summary of all available API functions and types.
8
8
 
9
9
  For detailed guides on specific features:
10
10
 
11
+ - **[SmartLinks Microapp Overview](overview.md)** - Platform architecture, data model, auth patterns, storage, anti-patterns, and quick-reference for all SDK docs
11
12
  - **[AI & Chat Completions](ai.md)** - Chat completions, RAG (document-grounded Q&A), voice integration, streaming, tool calling, podcast generation
12
13
  - **[Widgets](widgets.md)** - Embeddable React components for parent applications
13
14
  - **[Containers](containers.md)** - Building full-app embeddable containers (lazy-loaded)
15
+ - **[Multi-Page App Architecture](mpa.md)** - Vite MPA build pipeline: public/admin entry points, widget/container/executor bundles, content-hashed CDN assets
16
+ - **[App Configuration Files](app-manifest.md)** - `app.manifest.json` and `app.admin.json` reference — bundles, components, setup questions, import schemas, tunable fields, and metrics
17
+ - **[Executor Model](executor.md)** - Programmatic JS bundles for AI-driven setup, server-side SEO metadata generation, and LLM content for AI crawlers
14
18
  - **[Realtime](realtime.md)** - Real-time data updates and WebSocket connections
15
19
  - **[iframe Responder](iframe-responder.md)** - iframe integration and cross-origin communication
16
20
  - **[i18n](i18n.md)** - Internationalization and localization
@@ -21,7 +25,9 @@ For detailed guides on specific features:
21
25
  - **[App Data Storage](app-data-storage.md)** - User-specific and collection-scoped app data storage
22
26
  - **[App Objects: Cases, Threads & Records](app-objects.md)** - Generic app-scoped building blocks for support cases, discussions, bookings, registrations, and more
23
27
  - **[Communications](comms.md)** - Transactional sends, multi-channel broadcasts, consent management, push registration, and analytics
28
+ - **[Interactions & Event Tracking](interactions.md)** - Log user events, count outcomes, query history, and define interaction types with permissions
24
29
  - **[Deep Link Discovery](deep-link-discovery.md)** - Registering and discovering navigable app states for portal menus and AI orchestration
30
+ - **[AI-Native App Manifests](manifests.md)** - How AI workflows discover, configure, and import apps via structured manifests and prose guides
25
31
  - **[AI Guide Template](ai-guide-template.md)** - A sample for an app on how to build an AI setup guide
26
32
 
27
33
  ## API Namespaces
@@ -49,7 +55,7 @@ The Smartlinks SDK is organized into the following namespaces:
49
55
  - **segments** - Define dynamic/static audience segments; estimate and list recipients; schedule calculations.
50
56
 
51
57
  — Analytics & Events —
52
- - **interactions** - Log and analyze interactions/outcomes; aggregates and actor lists; interaction definition CRUD.
58
+ - **interactions** - Log and analyze interactions/outcomes; aggregates and actor lists; interaction definition CRUD. → [Guide](interactions.md)
53
59
 
54
60
  — Automation —
55
61
  - **journeys** - Configure automated flows triggered by events or schedules; steps, rules; full CRUD.
@@ -68,6 +74,8 @@ The Smartlinks SDK is organized into the following namespaces:
68
74
  - **appObjects** - Functions for appObjects operations
69
75
  - **async** - Functions for async operations
70
76
  - **attestation** - Functions for attestation operations
77
+ - **attestations** - Functions for attestations operations
78
+ - **containers** - Functions for containers operations
71
79
  - **jobs** - Functions for jobs operations
72
80
  - **journeysAnalytics** - Functions for journeysAnalytics operations
73
81
  - **location** - Functions for location operations
@@ -843,7 +851,11 @@ interface AppManifestFiles {
843
851
  umd: string;
844
852
  esm?: string;
845
853
  };
846
- css?: string;
854
+ * CSS file path — set to `null` (or omit) when the bundle ships no CSS.
855
+ * Most widgets and containers use Tailwind/shadcn classes from the parent and produce no CSS file.
856
+ * Only set to a non-null string if an actual CSS file exists in dist/;
857
+ * a non-null value pointing to a missing file will cause a 404 in the parent portal.
858
+ css?: string | null;
847
859
  }
848
860
  ```
849
861
 
@@ -873,6 +885,102 @@ interface AppContainerComponent {
873
885
  }
874
886
  ```
875
887
 
888
+ **DeepLinkEntry** (interface)
889
+ ```typescript
890
+ interface DeepLinkEntry {
891
+ title: string;
892
+ * Hash route path within the app (optional).
893
+ * Defaults to "/" if omitted.
894
+ * @example "/gallery"
895
+ path?: string;
896
+ * App-specific query params appended to the hash route URL.
897
+ * Do NOT include platform context params (collectionId, appId, productId, etc.) —
898
+ * those are injected by the platform automatically.
899
+ params?: Record<string, string>;
900
+ }
901
+ ```
902
+
903
+ **ExecutorContext** (interface)
904
+ ```typescript
905
+ interface ExecutorContext {
906
+ collectionId: string;
907
+ appId: string;
908
+ SL: any;
909
+ }
910
+ ```
911
+
912
+ **SEOInput** (interface)
913
+ ```typescript
914
+ interface SEOInput {
915
+ collectionId: string;
916
+ appId: string;
917
+ productId?: string;
918
+ proofId?: string;
919
+ SL: any;
920
+ collection?: Record<string, any>;
921
+ product?: Record<string, any>;
922
+ proof?: Record<string, any>;
923
+ }
924
+ ```
925
+
926
+ **SEOResult** (interface)
927
+ ```typescript
928
+ interface SEOResult {
929
+ title?: string;
930
+ description?: string;
931
+ ogImage?: string;
932
+ jsonLd?: Record<string, any> | Record<string, any>[];
933
+ contentSummary?: string;
934
+ topics?: string[];
935
+ }
936
+ ```
937
+
938
+ **LLMContentSection** (interface)
939
+ ```typescript
940
+ interface LLMContentSection {
941
+ heading: string;
942
+ content: string;
943
+ order?: number;
944
+ }
945
+ ```
946
+
947
+ **LLMContentInput** (interface)
948
+ ```typescript
949
+ interface LLMContentInput {
950
+ collectionId: string;
951
+ appId: string;
952
+ productId?: string;
953
+ proofId?: string;
954
+ SL: any;
955
+ collection?: Record<string, any>;
956
+ product?: Record<string, any>;
957
+ proof?: Record<string, any>;
958
+ pageSlug?: string;
959
+ }
960
+ ```
961
+
962
+ **LLMContentResult** (interface)
963
+ ```typescript
964
+ interface LLMContentResult {
965
+ sections: LLMContentSection[];
966
+ }
967
+ ```
968
+
969
+ **AppManifestExecutor** (interface)
970
+ ```typescript
971
+ interface AppManifestExecutor {
972
+ files: AppManifestFiles;
973
+ factory?: string;
974
+ exports?: string[];
975
+ description?: string;
976
+ llmContent?: {
977
+ function: string;
978
+ timeout?: number;
979
+ responseShape?: Record<string, any>;
980
+ };
981
+ }
982
+ ```
983
+
876
984
  **AppAdminConfig** (interface)
877
985
  ```typescript
878
986
  interface AppAdminConfig {
@@ -947,6 +1055,19 @@ interface AppManifest {
947
1055
  version: string;
948
1056
  platformRevision?: string;
949
1057
  appId: string;
1058
+ * SEO configuration for this app.
1059
+ * `priority` controls which app's singular fields (title, description, ogImage) win
1060
+ * when multiple apps appear on the same page. Default is 0; higher wins.
1061
+ seo?: {
1062
+ strategy?: 'executor' | string;
1063
+ priority?: number;
1064
+ contract?: {
1065
+ function: string;
1066
+ input?: string[];
1067
+ timeout?: number;
1068
+ responseShape?: Record<string, string>;
1069
+ };
1070
+ };
950
1071
  };
951
1072
  * Relative path to the admin configuration file (e.g. `"app.admin.json"`).
952
1073
  * When present, fetch this file to get the full {@link AppAdminConfig}
@@ -961,6 +1082,16 @@ interface AppManifest {
961
1082
  files: AppManifestFiles;
962
1083
  components: AppContainerComponent[];
963
1084
  };
1085
+ * Static deep-linkable states built into this app.
1086
+ * These are fixed routes that exist regardless of content — declared once at build time.
1087
+ * Dynamic content entries (e.g. CMS pages) are stored separately in `appConfig.linkable`.
1088
+ * Consumers should merge both sources to get the full set of navigable states.
1089
+ * @see DeepLinkEntry
1090
+ linkable?: DeepLinkEntry[];
1091
+ * Executor bundle declaration. Present when the app ships a programmatic executor
1092
+ * for AI-driven configuration, server-side SEO, and LLM content generation.
1093
+ * @see AppManifestExecutor
1094
+ executor?: AppManifestExecutor;
964
1095
  [key: string]: any;
965
1096
  }
966
1097
  ```
@@ -1454,6 +1585,230 @@ interface AttestationUpdateRequest {
1454
1585
  }
1455
1586
  ```
1456
1587
 
1588
+ ### attestations
1589
+
1590
+ **Attestation** (interface)
1591
+ ```typescript
1592
+ interface Attestation {
1593
+ id: string
1594
+ orgId: string
1595
+ collectionId: string
1596
+ subjectType: AttestationSubjectType
1597
+ subjectId: string
1598
+ attestationType: string
1599
+ recordedAt: string
1600
+ visibility: AttestationVisibility
1601
+ value?: Record<string, any>
1602
+ ownerData?: Record<string, any>
1603
+ adminData?: Record<string, any>
1604
+ unit?: string
1605
+ source?: string
1606
+ authorId?: string
1607
+ metadata?: Record<string, any>
1608
+ contentHash: string
1609
+ prevHash?: string
1610
+ createdAt: string
1611
+ }
1612
+ ```
1613
+
1614
+ **LatestAttestation** (interface)
1615
+ ```typescript
1616
+ interface LatestAttestation {
1617
+ attestationType: string
1618
+ latest: Attestation
1619
+ }
1620
+ ```
1621
+
1622
+ **AttestationSummaryBucket** (interface)
1623
+ ```typescript
1624
+ interface AttestationSummaryBucket {
1625
+ period: string
1626
+ count: number
1627
+ values?: Record<string, any>
1628
+ }
1629
+ ```
1630
+
1631
+ **ChainVerifyResult** (interface)
1632
+ ```typescript
1633
+ interface ChainVerifyResult {
1634
+ valid: boolean
1635
+ checkedCount: number
1636
+ failedAt?: string
1637
+ message: string
1638
+ }
1639
+ ```
1640
+
1641
+ **CreateAttestationInput** (interface)
1642
+ ```typescript
1643
+ interface CreateAttestationInput {
1644
+ subjectType: AttestationSubjectType
1645
+ subjectId: string
1646
+ attestationType: string
1647
+ recordedAt?: string
1648
+ visibility?: AttestationVisibility
1649
+ value?: Record<string, any>
1650
+ ownerData?: Record<string, any>
1651
+ adminData?: Record<string, any>
1652
+ unit?: string
1653
+ source?: string
1654
+ authorId?: string
1655
+ metadata?: Record<string, any>
1656
+ }
1657
+ ```
1658
+
1659
+ **ListAttestationsResponse** (interface)
1660
+ ```typescript
1661
+ interface ListAttestationsResponse {
1662
+ attestations: Attestation[]
1663
+ }
1664
+ ```
1665
+
1666
+ **PublicListAttestationsResponse** (interface)
1667
+ ```typescript
1668
+ interface PublicListAttestationsResponse {
1669
+ attestations: Attestation[]
1670
+ audience: AttestationAudience
1671
+ }
1672
+ ```
1673
+
1674
+ **AttestationSummaryResponse** (interface)
1675
+ ```typescript
1676
+ interface AttestationSummaryResponse {
1677
+ summary: AttestationSummaryBucket[]
1678
+ }
1679
+ ```
1680
+
1681
+ **PublicAttestationSummaryResponse** (interface)
1682
+ ```typescript
1683
+ interface PublicAttestationSummaryResponse {
1684
+ summary: AttestationSummaryBucket[]
1685
+ audience: 'public'
1686
+ }
1687
+ ```
1688
+
1689
+ **AttestationLatestResponse** (interface)
1690
+ ```typescript
1691
+ interface AttestationLatestResponse {
1692
+ latest: LatestAttestation[]
1693
+ }
1694
+ ```
1695
+
1696
+ **PublicAttestationLatestResponse** (interface)
1697
+ ```typescript
1698
+ interface PublicAttestationLatestResponse {
1699
+ latest: LatestAttestation[]
1700
+ audience: AttestationAudience
1701
+ }
1702
+ ```
1703
+
1704
+ **AttestationTreeSummaryResponse** (interface)
1705
+ ```typescript
1706
+ interface AttestationTreeSummaryResponse {
1707
+ summary: AttestationSummaryBucket[]
1708
+ subjectCount: number
1709
+ }
1710
+ ```
1711
+
1712
+ **PublicAttestationTreeSummaryResponse** (interface)
1713
+ ```typescript
1714
+ interface PublicAttestationTreeSummaryResponse {
1715
+ summary: AttestationSummaryBucket[]
1716
+ audience: 'public'
1717
+ subjectCount: number
1718
+ }
1719
+ ```
1720
+
1721
+ **AttestationTreeLatestResponse** (interface)
1722
+ ```typescript
1723
+ interface AttestationTreeLatestResponse {
1724
+ latest: LatestAttestation[]
1725
+ subjectCount: number
1726
+ }
1727
+ ```
1728
+
1729
+ **PublicAttestationTreeLatestResponse** (interface)
1730
+ ```typescript
1731
+ interface PublicAttestationTreeLatestResponse {
1732
+ latest: LatestAttestation[]
1733
+ audience: 'public'
1734
+ subjectCount: number
1735
+ }
1736
+ ```
1737
+
1738
+ **ListAttestationsParams** (interface)
1739
+ ```typescript
1740
+ interface ListAttestationsParams {
1741
+ subjectType: AttestationSubjectType
1742
+ subjectId: string
1743
+ attestationType?: string
1744
+ recordedAfter?: string
1745
+ recordedBefore?: string
1746
+ limit?: number
1747
+ offset?: number
1748
+ }
1749
+ ```
1750
+
1751
+ **AttestationSummaryParams** (interface)
1752
+ ```typescript
1753
+ interface AttestationSummaryParams {
1754
+ subjectType: AttestationSubjectType
1755
+ subjectId: string
1756
+ attestationType: string
1757
+ valueField?: string
1758
+ groupBy?: AttestationGroupBy
1759
+ recordedAfter?: string
1760
+ recordedBefore?: string
1761
+ limit?: number
1762
+ }
1763
+ ```
1764
+
1765
+ **AttestationLatestParams** (interface)
1766
+ ```typescript
1767
+ interface AttestationLatestParams {
1768
+ subjectType: AttestationSubjectType
1769
+ subjectId: string
1770
+ }
1771
+ ```
1772
+
1773
+ **AttestationVerifyParams** (interface)
1774
+ ```typescript
1775
+ interface AttestationVerifyParams {
1776
+ subjectType: AttestationSubjectType
1777
+ subjectId: string
1778
+ attestationType: string
1779
+ }
1780
+ ```
1781
+
1782
+ **AttestationTreeSummaryParams** (interface)
1783
+ ```typescript
1784
+ interface AttestationTreeSummaryParams {
1785
+ subjectId: string
1786
+ attestationType: string
1787
+ valueField?: string
1788
+ groupBy?: AttestationGroupBy
1789
+ recordedAfter?: string
1790
+ recordedBefore?: string
1791
+ limit?: number
1792
+ includeItems?: boolean
1793
+ }
1794
+ ```
1795
+
1796
+ **AttestationTreeLatestParams** (interface)
1797
+ ```typescript
1798
+ interface AttestationTreeLatestParams {
1799
+ subjectId: string
1800
+ includeItems?: boolean
1801
+ }
1802
+ ```
1803
+
1804
+ **AttestationSubjectType** = ``
1805
+
1806
+ **AttestationVisibility** = `'public' | 'owner' | 'admin'`
1807
+
1808
+ **AttestationAudience** = `'public' | 'owner' | 'admin'`
1809
+
1810
+ **AttestationGroupBy** = `'hour' | 'day' | 'week' | 'month'`
1811
+
1457
1812
  ### auth
1458
1813
 
1459
1814
  **UserAccountRegistrationRequest** (interface)
@@ -2956,6 +3311,184 @@ interface ContactSchemaResponse {
2956
3311
 
2957
3312
  **ContactSchema** = `ContactSchemaResponse`
2958
3313
 
3314
+ ### containers
3315
+
3316
+ **Container** (interface)
3317
+ ```typescript
3318
+ interface Container {
3319
+ id: string
3320
+ orgId: string
3321
+ collectionId: string
3322
+ * Domain label describing what kind of container this is.
3323
+ * Examples: `'pallet'`, `'fridge'`, `'cask'`, `'warehouse'`, `'shipping_container'`
3324
+ containerType: string
3325
+ ref?: string
3326
+ name?: string
3327
+ description?: string
3328
+ status: ContainerStatus
3329
+ metadata?: Record<string, any>
3330
+ parentContainerId?: string
3331
+ children?: Container[]
3332
+ items?: ContainerItem[]
3333
+ createdAt: string
3334
+ updatedAt: string
3335
+ deletedAt?: string
3336
+ }
3337
+ ```
3338
+
3339
+ **ContainerItem** (interface)
3340
+ ```typescript
3341
+ interface ContainerItem {
3342
+ id: string
3343
+ orgId: string
3344
+ containerId: string
3345
+ collectionId?: string
3346
+ itemType: ContainerItemType
3347
+ itemId: string
3348
+ productId?: string
3349
+ proofId?: string
3350
+ addedAt: string
3351
+ removedAt?: string
3352
+ metadata?: Record<string, any>
3353
+ }
3354
+ ```
3355
+
3356
+ **CreateContainerInput** (interface)
3357
+ ```typescript
3358
+ interface CreateContainerInput {
3359
+ containerType: string
3360
+ ref?: string
3361
+ name?: string
3362
+ description?: string
3363
+ status?: ContainerStatus
3364
+ metadata?: Record<string, any>
3365
+ parentContainerId?: string
3366
+ }
3367
+ ```
3368
+
3369
+ **UpdateContainerInput** (interface)
3370
+ ```typescript
3371
+ interface UpdateContainerInput {
3372
+ containerType?: string
3373
+ ref?: string
3374
+ name?: string
3375
+ description?: string
3376
+ status?: ContainerStatus
3377
+ metadata?: Record<string, any>
3378
+ parentContainerId?: string | null
3379
+ }
3380
+ ```
3381
+
3382
+ **AddContainerItemsInput** (interface)
3383
+ ```typescript
3384
+ interface AddContainerItemsInput {
3385
+ items: Array<{
3386
+ itemType: ContainerItemType
3387
+ itemId: string
3388
+ productId?: string
3389
+ proofId?: string
3390
+ metadata?: Record<string, any>
3391
+ }>
3392
+ }
3393
+ ```
3394
+
3395
+ **RemoveContainerItemsInput** (interface)
3396
+ ```typescript
3397
+ interface RemoveContainerItemsInput {
3398
+ ids: string[]
3399
+ }
3400
+ ```
3401
+
3402
+ **ListContainersResponse** (interface)
3403
+ ```typescript
3404
+ interface ListContainersResponse {
3405
+ containers: Container[]
3406
+ limit: number
3407
+ offset: number
3408
+ }
3409
+ ```
3410
+
3411
+ **PublicListContainersResponse** (interface)
3412
+ ```typescript
3413
+ interface PublicListContainersResponse {
3414
+ containers: Container[]
3415
+ }
3416
+ ```
3417
+
3418
+ **FindContainersForItemResponse** (interface)
3419
+ ```typescript
3420
+ interface FindContainersForItemResponse {
3421
+ containers: Container[]
3422
+ }
3423
+ ```
3424
+
3425
+ **ContainerItemsResponse** (interface)
3426
+ ```typescript
3427
+ interface ContainerItemsResponse {
3428
+ items: ContainerItem[]
3429
+ limit: number
3430
+ offset: number
3431
+ }
3432
+ ```
3433
+
3434
+ **AddContainerItemsResponse** (interface)
3435
+ ```typescript
3436
+ interface AddContainerItemsResponse {
3437
+ items: ContainerItem[]
3438
+ }
3439
+ ```
3440
+
3441
+ **RemoveContainerItemsResponse** (interface)
3442
+ ```typescript
3443
+ interface RemoveContainerItemsResponse {
3444
+ success: true
3445
+ removedCount: number
3446
+ }
3447
+ ```
3448
+
3449
+ **ListContainersParams** (interface)
3450
+ ```typescript
3451
+ interface ListContainersParams {
3452
+ containerType?: string
3453
+ status?: ContainerStatus
3454
+ ref?: string
3455
+ parentContainerId?: string
3456
+ topLevel?: boolean
3457
+ limit?: number
3458
+ offset?: number
3459
+ }
3460
+ ```
3461
+
3462
+ **GetContainerParams** (interface)
3463
+ ```typescript
3464
+ interface GetContainerParams {
3465
+ tree?: boolean
3466
+ treeDepth?: number
3467
+ includeContents?: boolean
3468
+ }
3469
+ ```
3470
+
3471
+ **ListContainerItemsParams** (interface)
3472
+ ```typescript
3473
+ interface ListContainerItemsParams {
3474
+ history?: boolean
3475
+ limit?: number
3476
+ offset?: number
3477
+ }
3478
+ ```
3479
+
3480
+ **FindContainersForItemParams** (interface)
3481
+ ```typescript
3482
+ interface FindContainersForItemParams {
3483
+ itemType: ContainerItemType
3484
+ itemId: string
3485
+ }
3486
+ ```
3487
+
3488
+ **ContainerStatus** = `'active' | 'archived' | string`
3489
+
3490
+ **ContainerItemType** = `'tag' | 'proof' | 'serial' | 'order_item' | 'container'`
3491
+
2959
3492
  ### crate
2960
3493
 
2961
3494
  **CrateItem** (interface)
@@ -4376,10 +4909,15 @@ interface Tag {
4376
4909
  orgId: string // Organization ID
4377
4910
  tagId: string // Unique tag identifier (globally unique)
4378
4911
  collectionId: string // Collection ID
4379
- productId: string // Product ID
4912
+ productId?: string // Product ID (optional — may be a ref-only tag)
4380
4913
  variantId?: string | null // Optional: Variant ID
4381
4914
  batchId?: string | null // Optional: Batch ID
4382
- proofId: string // Proof ID (serial number or explicit)
4915
+ proofId?: string // Proof ID (serial number or explicit)
4916
+ * Polymorphic reference type linking the tag to any app object, e.g.
4917
+ * `'app_record'`, `'app_case'`, `'container'`, etc.
4918
+ * Must always be paired with `refId`.
4919
+ refType?: string
4920
+ refId?: string
4383
4921
  metadata: Record<string, any> // Additional metadata (e.g., serialIndex)
4384
4922
  createdAt: string // ISO 8601 timestamp
4385
4923
  updatedAt: string // ISO 8601 timestamp
@@ -4390,11 +4928,15 @@ interface Tag {
4390
4928
  ```typescript
4391
4929
  interface CreateTagRequest {
4392
4930
  tagId: string // Required: Unique tag identifier
4393
- productId: string // Required: Product ID
4931
+ productId?: string // Optional: Product ID (required when proofId is set without useSerialNumber)
4394
4932
  variantId?: string // Optional: Variant ID
4395
4933
  batchId?: string // Optional: Batch ID
4396
- proofId?: string // Optional: Explicit proof ID (if omitted, auto-generates serial)
4934
+ proofId?: string // Optional: Explicit proof ID (if omitted with productId, auto-generates serial)
4397
4935
  useSerialNumber?: boolean // Optional: Explicitly request serial number generation
4936
+ * Polymorphic ref type linking this tag to any app object (e.g. `'app_record'`, `'container'`).
4937
+ * Must be paired with `refId`. A tag can simultaneously have a product/proof AND a ref.
4938
+ refType?: string
4939
+ refId?: string
4398
4940
  metadata?: Record<string, any> // Optional: Additional metadata
4399
4941
  force?: boolean // Optional: Overwrite if tag exists in same collection (default: false)
4400
4942
  }
@@ -4451,6 +4993,10 @@ interface UpdateTagRequest {
4451
4993
  variantId?: string | null // Optional: Update variant ID (null to clear)
4452
4994
  batchId?: string | null // Optional: Update batch ID (null to clear)
4453
4995
  proofId?: string // Optional: Update proof ID
4996
+ * Polymorphic ref type. Must be paired with `refId`.
4997
+ * Set both to `null` / omit to leave unchanged.
4998
+ refType?: string
4999
+ refId?: string
4454
5000
  metadata?: Record<string, any> // Optional: Merge with existing metadata
4455
5001
  }
4456
5002
  ```
@@ -4470,6 +5016,8 @@ interface ListTagsRequest {
4470
5016
  productId?: string // Optional: Filter by product ID
4471
5017
  variantId?: string // Optional: Filter by variant ID
4472
5018
  batchId?: string // Optional: Filter by batch ID
5019
+ refType?: string
5020
+ refId?: string
4473
5021
  }
4474
5022
  ```
4475
5023
 
@@ -4525,6 +5073,21 @@ interface PublicBatchLookupQueryRequest {
4525
5073
  }
4526
5074
  ```
4527
5075
 
5076
+ **ReverseTagLookupParams** (interface)
5077
+ ```typescript
5078
+ interface ReverseTagLookupParams {
5079
+ refType: string
5080
+ refId: string
5081
+ }
5082
+ ```
5083
+
5084
+ **ReverseTagLookupResponse** (interface)
5085
+ ```typescript
5086
+ interface ReverseTagLookupResponse {
5087
+ tags: Tag[]
5088
+ }
5089
+ ```
5090
+
4528
5091
  ### template
4529
5092
 
4530
5093
  **TemplateBase** (interface)
@@ -4951,13 +5514,91 @@ Create a new attestation for a proof.
4951
5514
  proofId: string,
4952
5515
  attestationId: string,
4953
5516
  data: AttestationUpdateRequest) → `Promise<AttestationResponse>`
4954
- Update an attestation.
5517
+ Update an attestation. via `attestations.create()` with a note in `metadata` instead.
4955
5518
 
4956
5519
  **remove**(collectionId: string,
4957
5520
  productId: string,
4958
5521
  proofId: string,
4959
5522
  attestationId: string) → `Promise<void>`
4960
- Delete an attestation.
5523
+ Delete an attestation. Use `attestations.create()` to append a corrective/superseding record instead.
5524
+
5525
+ ### attestations
5526
+
5527
+ **create**(collectionId: string,
5528
+ data: CreateAttestationInput) → `Promise<Attestation>`
5529
+ Create a single attestation (admin). `attestationType` are required ```typescript const a = await attestations.create('coll_123', { subjectType: 'container', subjectId: 'uuid-of-cask', attestationType: 'temperature', recordedAt: '2025-04-15T14:30:00Z', value: { celsius: 12.4 }, ownerData: { sensorId: 'TEMP-7' }, unit: '°C', visibility: 'public', }) ```
5530
+
5531
+ **createBatch**(collectionId: string,
5532
+ items: CreateAttestationInput[]) → `Promise<Attestation[]>`
5533
+ Batch-create attestations (admin). Sends an array of `CreateAttestationInput` objects in a single request. The server processes them atomically and returns the created records. ```typescript const records = await attestations.createBatch('coll_123', [ { subjectType: 'container', subjectId: 'uuid1', attestationType: 'temperature', value: { celsius: 12.4 } }, { subjectType: 'container', subjectId: 'uuid1', attestationType: 'humidity', value: { rh: 68 } }, ]) ```
5534
+
5535
+ **list**(collectionId: string,
5536
+ params: ListAttestationsParams) → `Promise<ListAttestationsResponse>`
5537
+ List attestations for a subject (admin). Returns all three data zones. Supports filtering by type and date range. ```typescript const { attestations: records } = await attestations.list('coll_123', { subjectType: 'container', subjectId: 'uuid-of-cask', attestationType: 'temperature', recordedAfter: '2025-01-01T00:00:00Z', limit: 50, }) ```
5538
+
5539
+ **summary**(collectionId: string,
5540
+ params: AttestationSummaryParams) → `Promise<AttestationSummaryResponse>`
5541
+ Time-series summary of attestations (admin). Aggregates attestation counts (and optionally a numeric `value` field) into time buckets. Useful for charting trends. `attestationType` are required ```typescript const { summary } = await attestations.summary('coll_123', { subjectType: 'container', subjectId: 'uuid-of-cask', attestationType: 'temperature', valueField: 'celsius', groupBy: 'day', recordedAfter: '2025-01-01T00:00:00Z', }) ```
5542
+
5543
+ **latest**(collectionId: string,
5544
+ params: AttestationLatestParams) → `Promise<AttestationLatestResponse>`
5545
+ Latest snapshot — one record per `attestationType` (admin). Returns the most-recent attestation for each type recorded against this subject. Ideal for dashboards that show the current state of a container. ```typescript const { latest } = await attestations.latest('coll_123', { subjectType: 'container', subjectId: 'uuid-of-fridge', }) // latest[0].attestationType === 'temperature' // latest[0].latest.value === { celsius: 4.1 } ```
5546
+
5547
+ **verify**(collectionId: string,
5548
+ params: AttestationVerifyParams) → `Promise<ChainVerifyResult>`
5549
+ Verify the hash chain for a `(subjectType, subjectId, attestationType)` tuple (admin). Re-computes each `contentHash` and confirms it matches the stored value and correctly references the previous record's hash. A `valid: false` result with `failedAt` indicates the first broken link. ```typescript const result = await attestations.verify('coll_123', { subjectType: 'container', subjectId: 'uuid-of-cask', attestationType: 'temperature', }) if (!result.valid) { console.warn('Chain broken at', result.failedAt) } ```
5550
+
5551
+ **treeSummary**(collectionId: string,
5552
+ params: AttestationTreeSummaryParams) → `Promise<AttestationTreeSummaryResponse>`
5553
+ Tree time-series summary — aggregates across an entire container subtree (admin). Performs a BFS traversal of the container hierarchy rooted at `subjectId`, collects all descendant container IDs (and optionally their items), then aggregates attestations across all of them. `subjectType` is implicitly `'container'` ```typescript const { summary, subjectCount } = await attestations.treeSummary('coll_123', { subjectId: 'root-warehouse-uuid', attestationType: 'temperature', valueField: 'celsius', groupBy: 'hour', includeItems: true, }) console.log(`Aggregated over ${subjectCount} subjects`) ```
5554
+
5555
+ **treeLatest**(collectionId: string,
5556
+ params: AttestationTreeLatestParams) → `Promise<AttestationTreeLatestResponse>`
5557
+ Tree latest snapshot — most-recent record per type across a container subtree (admin). Same BFS traversal as `treeSummary`, but returns the most-recent record per `attestationType` aggregated across the entire subtree.
5558
+
5559
+ **publicList**(collectionId: string,
5560
+ params: ListAttestationsParams) → `Promise<PublicListAttestationsResponse>`
5561
+ List attestations for a subject (public). Records with `visibility='admin'` are always excluded. Records with `visibility='owner'` are included only when the caller provides a valid Firebase ID token that resolves to the subject owner. The `audience` field in the response indicates the tier that was served. ```typescript const { attestations: records, audience } = await attestations.publicList('coll_123', { subjectType: 'proof', subjectId: 'proof-uuid', }) ```
5562
+
5563
+ **publicSummary**(collectionId: string,
5564
+ params: AttestationSummaryParams) → `Promise<PublicAttestationSummaryResponse>`
5565
+ Time-series summary (public). Always served at `audience='public'`. Same parameters as the admin version. `attestationType` are required
5566
+
5567
+ **publicLatest**(collectionId: string,
5568
+ params: AttestationLatestParams) → `Promise<PublicAttestationLatestResponse>`
5569
+ Latest snapshot per `attestationType` (public). Owner elevation applies — provide a Firebase ID token for owner-tier data.
5570
+
5571
+ **publicTreeSummary**(collectionId: string,
5572
+ params: AttestationTreeSummaryParams) → `Promise<PublicAttestationTreeSummaryResponse>`
5573
+ Tree time-series summary (public). Always served at `audience='public'`. Performs the same BFS traversal as the admin version but only includes publicly visible attestations.
5574
+
5575
+ **publicTreeLatest**(collectionId: string,
5576
+ params: AttestationTreeLatestParams) → `Promise<PublicAttestationTreeLatestResponse>`
5577
+ Tree latest snapshot (public).
5578
+
5579
+ **publicContainerList**(collectionId: string,
5580
+ containerId: string,
5581
+ params?: Omit<ListAttestationsParams, 'subjectType' | 'subjectId'>) → `Promise<PublicListAttestationsResponse>`
5582
+ List attestations for a specific container (public shortcut). Equivalent to `publicList` with `subjectType='container'` and `subjectId=containerId` pre-filled.
5583
+
5584
+ **publicContainerSummary**(collectionId: string,
5585
+ containerId: string,
5586
+ params: Omit<AttestationSummaryParams, 'subjectType' | 'subjectId'>) → `Promise<PublicAttestationSummaryResponse>`
5587
+ Time-series summary for a specific container (public shortcut).
5588
+
5589
+ **publicContainerLatest**(collectionId: string,
5590
+ containerId: string) → `Promise<PublicAttestationLatestResponse>`
5591
+ Latest snapshot for a specific container (public shortcut).
5592
+
5593
+ **publicContainerTreeSummary**(collectionId: string,
5594
+ containerId: string,
5595
+ params: Omit<AttestationTreeSummaryParams, 'subjectId'>) → `Promise<PublicAttestationTreeSummaryResponse>`
5596
+ Tree time-series summary rooted at a specific container (public shortcut).
5597
+
5598
+ **publicContainerTreeLatest**(collectionId: string,
5599
+ containerId: string,
5600
+ params?: Pick<AttestationTreeLatestParams, 'includeItems'>) → `Promise<PublicAttestationTreeLatestResponse>`
5601
+ Tree latest snapshot rooted at a specific container (public shortcut).
4961
5602
 
4962
5603
  ### auth
4963
5604
 
@@ -5378,6 +6019,63 @@ Public: Get the contact schema for a collection. GET /public/collection/:collect
5378
6019
  userId: string,) → `Promise<UserSearchResponse>`
5379
6020
  Public: Get the contact schema for a collection. GET /public/collection/:collectionId/contact/schema Returns a ContactSchemaResponse describing all publicly visible contact fields. Core fields and collection-defined custom fields are merged into a single flat schema. Fields not in `publicVisibleFields` are stripped entirely from the response. Fields visible but not in `publicEditableFields` have `ui:disabled: true` in `uiSchema`. Use `fieldOrder` to render fields in the correct sequence, and `evaluateConditions` from the types package to handle conditional field visibility. ```typescript import { contact, evaluateConditions } from '@proveanything/smartlinks' const schema = await contact.publicGetSchema(collectionId) for (const fieldId of schema.fieldOrder) { const property = schema.schema.properties[fieldId] const ui = schema.uiSchema[fieldId] || {} const visible = evaluateConditions(property.conditions, property.showWhen, formValues) const disabled = ui['ui:disabled'] === true if (visible) renderField({ fieldId, property, ui, disabled }) } ```
5380
6021
 
6022
+ ### containers
6023
+
6024
+ **create**(collectionId: string,
6025
+ data: CreateContainerInput) → `Promise<Container>`
6026
+ Create a new container (admin). ```typescript const cask = await containers.create('coll_123', { containerType: 'cask', ref: 'CASK-0042', name: 'Cask 42 — Single Malt', metadata: { distilleryYear: 2019, capacity: 200 }, }) ```
6027
+
6028
+ **list**(collectionId: string,
6029
+ params?: ListContainersParams) → `Promise<ListContainersResponse>`
6030
+ List containers (admin). Supports filtering by type, status, ref, parent, and top-level flag. ```typescript // All active pallets const { containers: pallets } = await containers.list('coll_123', { containerType: 'pallet', status: 'active', limit: 50, }) // Top-level containers only const { containers: roots } = await containers.list('coll_123', { topLevel: true }) ```
6031
+
6032
+ **findForItem**(collectionId: string,
6033
+ params: FindContainersForItemParams) → `Promise<FindContainersForItemResponse>`
6034
+ Reverse lookup — find all containers currently holding a specific item (admin). ```typescript const { containers: holding } = await containers.findForItem('coll_123', { itemType: 'proof', itemId: 'proof-uuid', }) ```
6035
+
6036
+ **get**(collectionId: string,
6037
+ containerId: string,
6038
+ params?: GetContainerParams) → `Promise<Container>`
6039
+ Get a single container by ID (admin). Pass `?tree=true` to recursively embed children, and/or `?includeContents=true` to embed the current item list. ```typescript // Flat const cask = await containers.get('coll_123', 'cask-uuid') // Full tree with contents const tree = await containers.get('coll_123', 'warehouse-uuid', { tree: true, treeDepth: 3, includeContents: true, }) ```
6040
+
6041
+ **update**(collectionId: string,
6042
+ containerId: string,
6043
+ data: UpdateContainerInput) → `Promise<Container>`
6044
+ Partially update a container (admin). Only fields present in the request body are modified. Pass `parentContainerId: null` to promote a container to top-level. ```typescript const updated = await containers.update('coll_123', 'cask-uuid', { status: 'archived', metadata: { bottledAt: '2025-04-01' }, }) ```
6045
+
6046
+ **remove**(collectionId: string,
6047
+ containerId: string) → `Promise<`
6048
+ Soft-delete a container (admin). Sets `deletedAt`; the record and its full item history remain queryable by admins. Public API responses automatically exclude deleted containers.
6049
+
6050
+ **listItems**(collectionId: string,
6051
+ containerId: string,
6052
+ params?: ListContainerItemsParams) → `Promise<ContainerItemsResponse>`
6053
+ List items currently (or historically) inside a container (admin). Pass `history: true` to include removed items and see the full membership log. ```typescript // Current contents const { items } = await containers.listItems('coll_123', 'cask-uuid') // Full history including removed items const { items: history } = await containers.listItems('coll_123', 'cask-uuid', { history: true }) ```
6054
+
6055
+ **addItems**(collectionId: string,
6056
+ containerId: string,
6057
+ data: AddContainerItemsInput) → `Promise<AddContainerItemsResponse>`
6058
+ Add one or more items to a container (admin). Each item requires `itemType` and `itemId`. Pass `productId` / `proofId` for denormalisation convenience. ```typescript const { items } = await containers.addItems('coll_123', 'pallet-uuid', { items: [ { itemType: 'tag', itemId: 'NFC-00AABBCC' }, { itemType: 'proof', itemId: 'proof-uuid', productId: 'product-id' }, ], }) ```
6059
+
6060
+ **removeItems**(collectionId: string,
6061
+ containerId: string,
6062
+ data: RemoveContainerItemsInput) → `Promise<RemoveContainerItemsResponse>`
6063
+ Soft-remove items from a container (admin). Sets `removedAt` on the specified `ContainerItem` records. The records are retained in the history log and can be queried with `history: true`. ```typescript const result = await containers.removeItems('coll_123', 'pallet-uuid', { ids: ['container-item-uuid-1', 'container-item-uuid-2'], }) console.log(`Removed ${result.removedCount} items`) ```
6064
+
6065
+ **publicList**(collectionId: string,
6066
+ params?: ListContainersParams) → `Promise<PublicListContainersResponse>`
6067
+ List containers (public). Soft-deleted containers and containers with `metadata.publicListing === false` are excluded from results.
6068
+
6069
+ **publicGet**(collectionId: string,
6070
+ containerId: string,
6071
+ params?: GetContainerParams) → `Promise<Container>`
6072
+ Get a single container (public). Soft-deleted containers return a 404. Same `?tree` and `?includeContents` options as the admin version.
6073
+
6074
+ **publicListItems**(collectionId: string,
6075
+ containerId: string,
6076
+ params?: Pick<ListContainerItemsParams, 'limit' | 'offset'>) → `Promise<ContainerItemsResponse>`
6077
+ List current contents of a container (public). Returns only items where `removedAt` is null. No `?history` option on the public side.
6078
+
5381
6079
  ### crate
5382
6080
 
5383
6081
  **list**(collectionId: string,
@@ -5866,6 +6564,10 @@ Get a single tag mapping by tagId. ```typescript const tag = await tags.get('col
5866
6564
  params?: ListTagsRequest) → `Promise<ListTagsResponse>`
5867
6565
  List all tags for a collection with optional filters and pagination. ```typescript // List all tags const all = await tags.list('coll_123') // List with filters const filtered = await tags.list('coll_123', { productId: 'prod_456', variantId: 'var_789', limit: 50, offset: 0 }) ```
5868
6566
 
6567
+ **byRef**(collectionId: string,
6568
+ params: ReverseTagLookupParams) → `Promise<ReverseTagLookupResponse>`
6569
+ Reverse lookup — find all tags linked to a given app object (admin). Uses a global cross-shard index keyed on `(orgId, refType, refId)`, so it is safe to call without knowing which collection the object belongs to. ```typescript const { tags: linked } = await tags.byRef('coll_123', { refType: 'container', refId: 'container-uuid', }) ```
6570
+
5869
6571
  **getTag**(tagId: string,
5870
6572
  params?: PublicGetTagRequest) → `Promise<PublicGetTagResponse>`
5871
6573
  Public lookup of a single tag by tagId (global). Optionally embed related collection, product, or proof data. No authentication required. ```typescript // Simple lookup const result = await tags.getTag('TAG001') // With embedded data const withData = await tags.getTag('TAG001', { embed: 'collection,product,proof' }) console.log(withData.tag, withData.collection, withData.product, withData.proof) ```