@proveanything/smartlinks 2.0.0-alpha.3 → 2.0.0-alpha.4

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.
@@ -10,6 +10,7 @@ export { auth } from "./auth";
10
10
  export { form } from "./form";
11
11
  export { authKit } from "./authKit";
12
12
  export { claimSet } from "./claimSet";
13
+ export { sequence } from "./sequence";
13
14
  export { crate } from "./crate";
14
15
  export { batch } from "./batch";
15
16
  export { variant } from "./variant";
package/dist/api/index.js CHANGED
@@ -12,6 +12,7 @@ export { auth } from "./auth";
12
12
  export { form } from "./form";
13
13
  export { authKit } from "./authKit";
14
14
  export { claimSet } from "./claimSet";
15
+ export { sequence } from "./sequence";
15
16
  export { crate } from "./crate";
16
17
  export { batch } from "./batch";
17
18
  export { variant } from "./variant";
@@ -0,0 +1,29 @@
1
+ export interface AllocateSequenceInput {
2
+ /** The app that owns the sequence config. */
3
+ appId: string;
4
+ /** The configured sequence id — the key of data.sequenceConfigs on the app config. */
5
+ sequenceId: string;
6
+ /** The STABLE subject identity — the claim-set id from the tap (NOT a per-tap virtual id). */
7
+ subjectId: string;
8
+ /** Optional product scope, when the sequence config is scoped per product. */
9
+ productId?: string;
10
+ }
11
+ export interface AllocatedSequence {
12
+ /** The allocated (or already-held) number. */
13
+ number: number;
14
+ /** True when this call allocated a new number; false when the subject already had one. */
15
+ isNew: boolean;
16
+ }
17
+ export declare namespace sequence {
18
+ /**
19
+ * Allocate (or return the existing) sequence number for a subject. Idempotent — safe to
20
+ * call on load (auto-enter) and on a button tap; a subject that already has a number gets
21
+ * it back with `isNew: false`.
22
+ *
23
+ * @example
24
+ * const { number, isNew } = await sequence.allocate(collectionId, {
25
+ * appId: 'raffle-app', sequenceId: 'raffle', subjectId: claimSetId,
26
+ * })
27
+ */
28
+ function allocate(collectionId: string, input: AllocateSequenceInput): Promise<AllocatedSequence>;
29
+ }
@@ -0,0 +1,26 @@
1
+ // src/api/sequence.ts
2
+ //
3
+ // Sequences — allocate a guaranteed-unique, monotonic number (raffle tickets, "Nth to
4
+ // claim", queue positions) and stamp it onto a record. The sequence (counter key, target,
5
+ // field, scope) is configured server-side in app config (data.sequenceConfigs[sequenceId]);
6
+ // this call supplies only the subject and is idempotent — a re-tap returns the same number.
7
+ // See docs/sequences.md.
8
+ import { post } from "../http";
9
+ export var sequence;
10
+ (function (sequence) {
11
+ const base = (collectionId) => `/public/collection/${encodeURIComponent(collectionId)}/sequence`;
12
+ /**
13
+ * Allocate (or return the existing) sequence number for a subject. Idempotent — safe to
14
+ * call on load (auto-enter) and on a button tap; a subject that already has a number gets
15
+ * it back with `isNew: false`.
16
+ *
17
+ * @example
18
+ * const { number, isNew } = await sequence.allocate(collectionId, {
19
+ * appId: 'raffle-app', sequenceId: 'raffle', subjectId: claimSetId,
20
+ * })
21
+ */
22
+ async function allocate(collectionId, input) {
23
+ return post(`${base(collectionId)}/allocate`, input);
24
+ }
25
+ sequence.allocate = allocate;
26
+ })(sequence || (sequence = {}));
@@ -1,6 +1,6 @@
1
1
  # Smartlinks API Summary
2
2
 
3
- Version: 2.0.0-alpha.3 | Generated: 2026-09-14T14:38:59.597Z
3
+ Version: 2.0.0-alpha.4 | Generated: 2026-09-14T15:08:56.614Z
4
4
 
5
5
  This is a concise summary of all available API functions and types.
6
6
 
@@ -150,6 +150,7 @@ The Smartlinks SDK is organized into the following namespaces:
150
150
  - **realtime** - Functions for realtime operations
151
151
  - **research** - Functions for research operations
152
152
  - **secrets** - Functions for secrets operations
153
+ - **sequence** - Functions for sequence operations
153
154
  - **tags** - Functions for tags operations
154
155
  - **template** - Functions for template operations
155
156
  - **translations** - Functions for translations operations
@@ -8535,6 +8536,26 @@ type VerifyTokenResponse = {
8535
8536
  }
8536
8537
  ```
8537
8538
 
8539
+ ### sequence (api)
8540
+
8541
+ **AllocateSequenceInput** (interface)
8542
+ ```typescript
8543
+ interface AllocateSequenceInput {
8544
+ appId: string
8545
+ sequenceId: string
8546
+ subjectId: string
8547
+ productId?: string
8548
+ }
8549
+ ```
8550
+
8551
+ **AllocatedSequence** (interface)
8552
+ ```typescript
8553
+ interface AllocatedSequence {
8554
+ number: number
8555
+ isNew: boolean
8556
+ }
8557
+ ```
8558
+
8538
8559
  ### conditions (utils)
8539
8560
 
8540
8561
  **BaseCondition** (interface)
@@ -10791,6 +10812,11 @@ Soft-delete a secret. DELETE /secrets/:ref
10791
10812
  id: string,
10792
10813
  query: { limit?: number; offset?: number } = {}) → `Promise<SegmentRecipientsResponse>`
10793
10814
 
10815
+ ### sequence
10816
+
10817
+ **allocate**(collectionId: string, input: AllocateSequenceInput) → `Promise<AllocatedSequence>`
10818
+ Allocate (or return the existing) sequence number for a subject. Idempotent — safe to call on load (auto-enter) and on a button tap; a subject that already has a number gets it back with `isNew: false`. const { number, isNew } = await sequence.allocate(collectionId, { appId: 'raffle-app', sequenceId: 'raffle', subjectId: claimSetId, })
10819
+
10794
10820
  ### sessions
10795
10821
 
10796
10822
  **stats**(collectionId: string) → `Promise<SessionStatistics>`
@@ -62,30 +62,47 @@ The stamp target is configurable — the number lives wherever you'll read it:
62
62
  | `proof` | A minted proof (value or attestation) — when the number should travel with the proof. |
63
63
  | `appRecord` | A structured app record — for queryable, per-app data. |
64
64
 
65
- ## Worked example a free raffle on NFC wristbands
65
+ ## Configure the sequence (once, server-side)
66
66
 
67
- Everyone taps a wristband and hits **Enter the raffle**. Each tap allocates the next number
68
- and writes it onto that wristband's claim set fast, unique, no proof mint:
67
+ You define the sequence **in your app config**, under `data.sequenceConfigs`. This is what
68
+ makes the public endpoint safe: the target/field/scope are set by you, not the caller.
69
69
 
70
70
  ```jsonc
71
- // allocate-and-stamp (conceptual shape)
71
+ // app config: data.sequenceConfigs
72
72
  {
73
- "appId": "raffle-app",
74
- "productId": "wristbands-2026", // the counter's scope
75
- "key": "raffle:2026-cup", // the named sequence
76
- "start": 1,
77
- "subjectId": "<claim set id>", // STABLE identity re-taps collapse to one number
78
- "target": "claimSet",
79
- "field": "raffleNumber"
73
+ "raffle": {
74
+ "key": "raffle:2026-cup", // the named counter (data.sequences.<key>)
75
+ "target": "claimSet", // claimSet | proof | appRecord — where the number is stamped
76
+ "field": "raffleNumber", // the property written on the target
77
+ "productId": "wristbands-2026", // counter scope (optional; else collection-wide)
78
+ "start": 1 // first number (optional, default 1)
79
+ }
80
80
  }
81
- // → { "number": 42, "isNew": true } (re-tap → { "number": 42, "isNew": false })
82
81
  ```
83
82
 
84
- Drawing the winner needs no separate ledger either — query the claim sets (or proofs) where
85
- `raffleNumber` is set; that field is your entry list, in allocation order.
83
+ ## Call it (the widget)
86
84
 
87
- ## Status
85
+ Your widget calls one bounded, public endpoint on tap. It passes only the **subject id** —
86
+ never the target/field:
88
87
 
89
- The allocator + stamping run server-side today. The **public "enter" action** an app widget
90
- calls on tap (and its SDK wrapper) is being wired in the 2.0.0-alpha line — this doc is the
91
- contract it will expose.
88
+ ```
89
+ POST /api/v1/public/collection/:collectionId/sequence/allocate
90
+ { "appId": "raffle-app", "sequenceId": "raffle", "subjectId": "<claim set id>" }
91
+ → { "number": 42, "isNew": true } // re-tap → { "number": 42, "isNew": false }
92
+ ```
93
+
94
+ - **`subjectId`** is the STABLE identity — the claim-set id from the tap. Re-taps collapse to
95
+ one number.
96
+ - **Idempotent**, so both your flows are the *same call*:
97
+ - **Auto:** on load, call allocate → get your number (existing or freshly minted).
98
+ - **Button:** click → animate → same call → "Your raffle number is 42."
99
+ - **Refresh:** just read the `raffleNumber` field back off the claim set (or proof) — it's the
100
+ ledger. Or call allocate again; you'll get the same number with `isNew: false`.
101
+
102
+ Errors: `404 SEQUENCE_NOT_FOUND` (not configured), `404 CLAIMSET_NOT_FOUND` (bad subject),
103
+ `400 BAD_REQUEST` (missing fields).
104
+
105
+ ## Drawing the winner
106
+
107
+ No separate ledger — query the claim sets (or proofs) where `raffleNumber` is set; that field
108
+ is your entry list, in allocation order.
package/dist/openapi.yaml CHANGED
@@ -27897,3 +27897,28 @@ components:
27897
27897
  additionalProperties: true
27898
27898
  required:
27899
27899
  - valid
27900
+ AllocateSequenceInput:
27901
+ type: object
27902
+ properties:
27903
+ appId:
27904
+ type: string
27905
+ sequenceId:
27906
+ type: string
27907
+ subjectId:
27908
+ type: string
27909
+ productId:
27910
+ type: string
27911
+ required:
27912
+ - appId
27913
+ - sequenceId
27914
+ - subjectId
27915
+ AllocatedSequence:
27916
+ type: object
27917
+ properties:
27918
+ number:
27919
+ type: number
27920
+ isNew:
27921
+ type: boolean
27922
+ required:
27923
+ - number
27924
+ - isNew
@@ -1,6 +1,6 @@
1
1
  # Smartlinks API Summary
2
2
 
3
- Version: 2.0.0-alpha.3 | Generated: 2026-09-14T14:38:59.597Z
3
+ Version: 2.0.0-alpha.4 | Generated: 2026-09-14T15:08:56.614Z
4
4
 
5
5
  This is a concise summary of all available API functions and types.
6
6
 
@@ -150,6 +150,7 @@ The Smartlinks SDK is organized into the following namespaces:
150
150
  - **realtime** - Functions for realtime operations
151
151
  - **research** - Functions for research operations
152
152
  - **secrets** - Functions for secrets operations
153
+ - **sequence** - Functions for sequence operations
153
154
  - **tags** - Functions for tags operations
154
155
  - **template** - Functions for template operations
155
156
  - **translations** - Functions for translations operations
@@ -8535,6 +8536,26 @@ type VerifyTokenResponse = {
8535
8536
  }
8536
8537
  ```
8537
8538
 
8539
+ ### sequence (api)
8540
+
8541
+ **AllocateSequenceInput** (interface)
8542
+ ```typescript
8543
+ interface AllocateSequenceInput {
8544
+ appId: string
8545
+ sequenceId: string
8546
+ subjectId: string
8547
+ productId?: string
8548
+ }
8549
+ ```
8550
+
8551
+ **AllocatedSequence** (interface)
8552
+ ```typescript
8553
+ interface AllocatedSequence {
8554
+ number: number
8555
+ isNew: boolean
8556
+ }
8557
+ ```
8558
+
8538
8559
  ### conditions (utils)
8539
8560
 
8540
8561
  **BaseCondition** (interface)
@@ -10791,6 +10812,11 @@ Soft-delete a secret. DELETE /secrets/:ref
10791
10812
  id: string,
10792
10813
  query: { limit?: number; offset?: number } = {}) → `Promise<SegmentRecipientsResponse>`
10793
10814
 
10815
+ ### sequence
10816
+
10817
+ **allocate**(collectionId: string, input: AllocateSequenceInput) → `Promise<AllocatedSequence>`
10818
+ Allocate (or return the existing) sequence number for a subject. Idempotent — safe to call on load (auto-enter) and on a button tap; a subject that already has a number gets it back with `isNew: false`. const { number, isNew } = await sequence.allocate(collectionId, { appId: 'raffle-app', sequenceId: 'raffle', subjectId: claimSetId, })
10819
+
10794
10820
  ### sessions
10795
10821
 
10796
10822
  **stats**(collectionId: string) → `Promise<SessionStatistics>`
package/docs/sequences.md CHANGED
@@ -62,30 +62,47 @@ The stamp target is configurable — the number lives wherever you'll read it:
62
62
  | `proof` | A minted proof (value or attestation) — when the number should travel with the proof. |
63
63
  | `appRecord` | A structured app record — for queryable, per-app data. |
64
64
 
65
- ## Worked example a free raffle on NFC wristbands
65
+ ## Configure the sequence (once, server-side)
66
66
 
67
- Everyone taps a wristband and hits **Enter the raffle**. Each tap allocates the next number
68
- and writes it onto that wristband's claim set fast, unique, no proof mint:
67
+ You define the sequence **in your app config**, under `data.sequenceConfigs`. This is what
68
+ makes the public endpoint safe: the target/field/scope are set by you, not the caller.
69
69
 
70
70
  ```jsonc
71
- // allocate-and-stamp (conceptual shape)
71
+ // app config: data.sequenceConfigs
72
72
  {
73
- "appId": "raffle-app",
74
- "productId": "wristbands-2026", // the counter's scope
75
- "key": "raffle:2026-cup", // the named sequence
76
- "start": 1,
77
- "subjectId": "<claim set id>", // STABLE identity re-taps collapse to one number
78
- "target": "claimSet",
79
- "field": "raffleNumber"
73
+ "raffle": {
74
+ "key": "raffle:2026-cup", // the named counter (data.sequences.<key>)
75
+ "target": "claimSet", // claimSet | proof | appRecord — where the number is stamped
76
+ "field": "raffleNumber", // the property written on the target
77
+ "productId": "wristbands-2026", // counter scope (optional; else collection-wide)
78
+ "start": 1 // first number (optional, default 1)
79
+ }
80
80
  }
81
- // → { "number": 42, "isNew": true } (re-tap → { "number": 42, "isNew": false })
82
81
  ```
83
82
 
84
- Drawing the winner needs no separate ledger either — query the claim sets (or proofs) where
85
- `raffleNumber` is set; that field is your entry list, in allocation order.
83
+ ## Call it (the widget)
86
84
 
87
- ## Status
85
+ Your widget calls one bounded, public endpoint on tap. It passes only the **subject id** —
86
+ never the target/field:
88
87
 
89
- The allocator + stamping run server-side today. The **public "enter" action** an app widget
90
- calls on tap (and its SDK wrapper) is being wired in the 2.0.0-alpha line — this doc is the
91
- contract it will expose.
88
+ ```
89
+ POST /api/v1/public/collection/:collectionId/sequence/allocate
90
+ { "appId": "raffle-app", "sequenceId": "raffle", "subjectId": "<claim set id>" }
91
+ → { "number": 42, "isNew": true } // re-tap → { "number": 42, "isNew": false }
92
+ ```
93
+
94
+ - **`subjectId`** is the STABLE identity — the claim-set id from the tap. Re-taps collapse to
95
+ one number.
96
+ - **Idempotent**, so both your flows are the *same call*:
97
+ - **Auto:** on load, call allocate → get your number (existing or freshly minted).
98
+ - **Button:** click → animate → same call → "Your raffle number is 42."
99
+ - **Refresh:** just read the `raffleNumber` field back off the claim set (or proof) — it's the
100
+ ledger. Or call allocate again; you'll get the same number with `isNew: false`.
101
+
102
+ Errors: `404 SEQUENCE_NOT_FOUND` (not configured), `404 CLAIMSET_NOT_FOUND` (bad subject),
103
+ `400 BAD_REQUEST` (missing fields).
104
+
105
+ ## Drawing the winner
106
+
107
+ No separate ledger — query the claim sets (or proofs) where `raffleNumber` is set; that field
108
+ is your entry list, in allocation order.
package/openapi.yaml CHANGED
@@ -27897,3 +27897,28 @@ components:
27897
27897
  additionalProperties: true
27898
27898
  required:
27899
27899
  - valid
27900
+ AllocateSequenceInput:
27901
+ type: object
27902
+ properties:
27903
+ appId:
27904
+ type: string
27905
+ sequenceId:
27906
+ type: string
27907
+ subjectId:
27908
+ type: string
27909
+ productId:
27910
+ type: string
27911
+ required:
27912
+ - appId
27913
+ - sequenceId
27914
+ - subjectId
27915
+ AllocatedSequence:
27916
+ type: object
27917
+ properties:
27918
+ number:
27919
+ type: number
27920
+ isNew:
27921
+ type: boolean
27922
+ required:
27923
+ - number
27924
+ - isNew
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proveanything/smartlinks",
3
- "version": "2.0.0-alpha.3",
3
+ "version": "2.0.0-alpha.4",
4
4
  "description": "Official JavaScript/TypeScript SDK for the Smartlinks API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",