@1claw/openapi-spec 0.61.48 → 0.61.50

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 (3) hide show
  1. package/openapi.json +415 -1
  2. package/openapi.yaml +304 -1
  3. package/package.json +2 -2
package/openapi.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "1Claw API",
5
- "version": "0.61.48",
5
+ "version": "0.61.50",
6
6
  "description": "Secure secret management for AI agents. Provides vaults, secrets,\npolicy-based access control, agent identity, Intents API,\nsharing, billing, and audit logging. Automations (workflow_spec,\nwebhook tokens, event triggers, Assist), cloud runtimes with\ninteractive shell sessions, agent memory, and discovery.\n\n## Domains\n\n`api.1claw.co` is canonical: it is the OIDC issuer, the `aud` the API\nmints, and the first entry in `servers` — a generated client takes its\nbase URL from there, and the previous ordering pointed every SDK at the\ndomain the issuer had already left. `api.1claw.xyz` still answers and is\nstill accepted on token validation, because tokens minted before the\nmove carry it; it is never minted now.\n\nOne deliberate exception: the Shroud attestation identity token is\nrequested from GCP with `audience: https://api.1claw.xyz`, so\n`/v1/shroud/attestation` reports that as its `expected_audience`. That\nis accurate rather than stale — the audience is a verification contract\nwith anyone already checking the token, and moving it is a breaking\nchange for them, not a rename.\n\nAll endpoints require JWT Bearer authentication unless marked with\n`security: []`.\n",
7
7
  "contact": {
8
8
  "email": "ops@1claw.co"
@@ -7026,6 +7026,38 @@
7026
7026
  }
7027
7027
  }
7028
7028
  },
7029
+ "/v1/referrals/me": {
7030
+ "get": {
7031
+ "tags": [
7032
+ "Organization"
7033
+ ],
7034
+ "summary": "Your own referral link and signups",
7035
+ "description": "The caller's referral code, the link to share, how many signups it has\nproduced, and a recent list.\n\nUsers only — a referral link belongs to a person, so an agent principal\ngets 403.\n\nThe link's host comes from the brand the request arrived on, the same\nway the SIWE domain and the WebAuthn rpId do: someone on 1claw.co must\nnot be handed a 1claw.xyz link to post.\n\n`recent[].referred_hint` is masked (`a**@example.com`) — enough to\nrecognise someone you did invite, not enough to contact someone you did\nnot. Neither the referred address nor its user id is returned.\n",
7036
+ "operationId": "getMyReferrals",
7037
+ "responses": {
7038
+ "200": {
7039
+ "description": "The caller's referral code, link and signup count",
7040
+ "content": {
7041
+ "application/json": {
7042
+ "schema": {
7043
+ "$ref": "#/components/schemas/MyReferralsResponse"
7044
+ }
7045
+ }
7046
+ }
7047
+ },
7048
+ "403": {
7049
+ "description": "The caller is an agent, not a person.",
7050
+ "content": {
7051
+ "application/json": {
7052
+ "schema": {
7053
+ "$ref": "#/components/schemas/ProblemDetails"
7054
+ }
7055
+ }
7056
+ }
7057
+ }
7058
+ }
7059
+ }
7060
+ },
7029
7061
  "/v1/onboarding/provision": {
7030
7062
  "post": {
7031
7063
  "tags": [
@@ -7760,6 +7792,194 @@
7760
7792
  }
7761
7793
  }
7762
7794
  },
7795
+ "/v1/staking/points": {
7796
+ "get": {
7797
+ "tags": [
7798
+ "Billing"
7799
+ ],
7800
+ "summary": "Staking points for the signed-in user's wallet",
7801
+ "description": "Points earned by staking, what has been redeemed here, and what is\nleft.\n\nThe two halves come from different places on purpose. `earned` is\nread per request from the staking service, which recomputes it from\non-chain events; `spent` is this service's own append-only ledger.\n`available` is the difference, floored at zero.\n\nThe wallet is the one on the account, proven by a SIWE signature at\nsign-in — there is no way to ask about another address.\n\n`can_redeem` is false until the account has a real, verified email:\na wallet signature proves possession of a key, not a reachable\nperson, and `redeem_blocked_reason` says what to do about it.\n",
7802
+ "operationId": "getStakingPoints",
7803
+ "responses": {
7804
+ "200": {
7805
+ "description": "Points and rates",
7806
+ "content": {
7807
+ "application/json": {
7808
+ "schema": {
7809
+ "type": "object",
7810
+ "properties": {
7811
+ "wallet_address": {
7812
+ "type": "string"
7813
+ },
7814
+ "earned": {
7815
+ "type": "integer",
7816
+ "format": "int64"
7817
+ },
7818
+ "spent": {
7819
+ "type": "integer",
7820
+ "format": "int64"
7821
+ },
7822
+ "available": {
7823
+ "type": "integer",
7824
+ "format": "int64"
7825
+ },
7826
+ "can_redeem": {
7827
+ "type": "boolean"
7828
+ },
7829
+ "redeem_blocked_reason": {
7830
+ "type": "string",
7831
+ "nullable": true
7832
+ },
7833
+ "rates": {
7834
+ "type": "object",
7835
+ "properties": {
7836
+ "points_per_pro_month": {
7837
+ "type": "integer"
7838
+ },
7839
+ "micro_usd_per_point": {
7840
+ "type": "integer"
7841
+ },
7842
+ "points_per_day_per_100m_tokens": {
7843
+ "type": "integer"
7844
+ },
7845
+ "max_pro_months_per_redemption": {
7846
+ "type": "integer"
7847
+ }
7848
+ }
7849
+ },
7850
+ "recent": {
7851
+ "type": "array",
7852
+ "items": {
7853
+ "type": "object",
7854
+ "properties": {
7855
+ "id": {
7856
+ "type": "string",
7857
+ "format": "uuid"
7858
+ },
7859
+ "wallet_address": {
7860
+ "type": "string"
7861
+ },
7862
+ "points_spent": {
7863
+ "type": "integer",
7864
+ "format": "int64"
7865
+ },
7866
+ "reward_type": {
7867
+ "type": "string",
7868
+ "enum": [
7869
+ "pro_months",
7870
+ "credits"
7871
+ ]
7872
+ },
7873
+ "reward_detail": {
7874
+ "type": "object"
7875
+ },
7876
+ "created_at": {
7877
+ "type": "string",
7878
+ "format": "date-time"
7879
+ }
7880
+ }
7881
+ }
7882
+ }
7883
+ }
7884
+ }
7885
+ }
7886
+ }
7887
+ },
7888
+ "400": {
7889
+ "description": "No wallet linked to this account"
7890
+ },
7891
+ "403": {
7892
+ "description": "Only a signed-in person can read staking points"
7893
+ },
7894
+ "503": {
7895
+ "description": "The staking service could not report points. Deliberately not\nreported as zero — that would tell a staker their earnings\nhad vanished.\n"
7896
+ }
7897
+ }
7898
+ }
7899
+ },
7900
+ "/v1/staking/redeem": {
7901
+ "post": {
7902
+ "tags": [
7903
+ "Billing"
7904
+ ],
7905
+ "summary": "Redeem staking points for plan time or credits",
7906
+ "description": "Spends points from the wallet on the account.\n\n`quantity` is **months** for `pro_months` and **points** for\n`credits`; the response always states the cost actually charged.\n\nPro months extend an existing period rather than replacing it, so\nredeeming twice does not discard the time already granted. They are\nrefused when the organisation has a Stripe subscription, or is on a\ntier above Pro: a comped tier would overwrite the plan being paid\nfor and would never expire. Credits apply on top of a subscription\nand are the right choice there.\n\nRedemption serialises on the wallet's ledger, so two concurrent\nrequests cannot spend the same points.\n",
7907
+ "operationId": "redeemStakingPoints",
7908
+ "requestBody": {
7909
+ "required": true,
7910
+ "content": {
7911
+ "application/json": {
7912
+ "schema": {
7913
+ "type": "object",
7914
+ "required": [
7915
+ "reward_type",
7916
+ "quantity"
7917
+ ],
7918
+ "properties": {
7919
+ "reward_type": {
7920
+ "type": "string",
7921
+ "enum": [
7922
+ "pro_months",
7923
+ "credits"
7924
+ ]
7925
+ },
7926
+ "quantity": {
7927
+ "type": "integer",
7928
+ "format": "int64",
7929
+ "minimum": 1,
7930
+ "description": "Months for pro_months; points for credits"
7931
+ }
7932
+ }
7933
+ }
7934
+ }
7935
+ }
7936
+ },
7937
+ "responses": {
7938
+ "200": {
7939
+ "description": "Redeemed",
7940
+ "content": {
7941
+ "application/json": {
7942
+ "schema": {
7943
+ "type": "object",
7944
+ "properties": {
7945
+ "redemption_id": {
7946
+ "type": "string",
7947
+ "format": "uuid"
7948
+ },
7949
+ "points_spent": {
7950
+ "type": "integer",
7951
+ "format": "int64"
7952
+ },
7953
+ "remaining_available": {
7954
+ "type": "integer",
7955
+ "format": "int64"
7956
+ },
7957
+ "reward_type": {
7958
+ "type": "string"
7959
+ },
7960
+ "reward_detail": {
7961
+ "type": "object"
7962
+ }
7963
+ }
7964
+ }
7965
+ }
7966
+ }
7967
+ },
7968
+ "400": {
7969
+ "description": "Not enough points, or no wallet linked"
7970
+ },
7971
+ "403": {
7972
+ "description": "A real verified email is required before redeeming"
7973
+ },
7974
+ "409": {
7975
+ "description": "Pro months refused because the organisation's billing is owned\nby Stripe, or its tier is above Pro. Redeem credits instead.\n"
7976
+ },
7977
+ "503": {
7978
+ "description": "The staking service could not report points; nothing was charged"
7979
+ }
7980
+ }
7981
+ }
7982
+ },
7763
7983
  "/v1/billing/credits/topup": {
7764
7984
  "post": {
7765
7985
  "tags": [
@@ -17674,6 +17894,143 @@
17674
17894
  }
17675
17895
  }
17676
17896
  },
17897
+ "/v1/auth/siwe/challenge": {
17898
+ "post": {
17899
+ "tags": [
17900
+ "Authentication"
17901
+ ],
17902
+ "summary": "Start wallet sign-in (SIWE)",
17903
+ "description": "Returns the exact EIP-4361 message to sign, for signing in to the\ndashboard with an Ethereum wallet.\n\nThe message is built server-side and returned whole: the domain and\nthe nonce are ours to decide, and a client that assembles its own\nmessage is a client that can be talked into signing a different\none. Sign it unmodified and post it back to\n`/v1/auth/siwe/verify`.\n\nThe nonce is single-use and valid for five minutes. Distinct from\n`/v1/platform/siwe/challenge`, which needs a `plt_` caller and\nissues nonces scoped to one platform app for *its* end users.\n",
17904
+ "operationId": "siweLoginChallenge",
17905
+ "security": [],
17906
+ "requestBody": {
17907
+ "required": true,
17908
+ "content": {
17909
+ "application/json": {
17910
+ "schema": {
17911
+ "type": "object",
17912
+ "required": [
17913
+ "address"
17914
+ ],
17915
+ "properties": {
17916
+ "address": {
17917
+ "type": "string",
17918
+ "description": "0x-prefixed 20-byte Ethereum address",
17919
+ "example": "0x0000000000000000000000000000000000000001"
17920
+ }
17921
+ }
17922
+ }
17923
+ }
17924
+ }
17925
+ },
17926
+ "responses": {
17927
+ "200": {
17928
+ "description": "Message to sign",
17929
+ "content": {
17930
+ "application/json": {
17931
+ "schema": {
17932
+ "type": "object",
17933
+ "properties": {
17934
+ "message": {
17935
+ "type": "string",
17936
+ "description": "Sign this verbatim"
17937
+ },
17938
+ "nonce": {
17939
+ "type": "string"
17940
+ },
17941
+ "expires_in_secs": {
17942
+ "type": "integer"
17943
+ }
17944
+ }
17945
+ }
17946
+ }
17947
+ }
17948
+ },
17949
+ "400": {
17950
+ "description": "Not a valid Ethereum address"
17951
+ },
17952
+ "429": {
17953
+ "description": "Rate limited"
17954
+ }
17955
+ }
17956
+ }
17957
+ },
17958
+ "/v1/auth/siwe/verify": {
17959
+ "post": {
17960
+ "tags": [
17961
+ "Authentication"
17962
+ ],
17963
+ "summary": "Complete wallet sign-in and get a JWT",
17964
+ "description": "Verifies the signature over the challenge message and returns an\nordinary user JWT — the same token social login and email-OTP\nproduce.\n\nFirst sign-in for an address creates a user and org. That user's\nemail starts synthetic (`email_pending: true`) and unverified: a\nwallet signature proves possession of a key, not a reachable\nperson. Staking redemption refuses until a real address is added\nand confirmed.\n\nThe wallet recovered from the signature is stored on the account\nand is the identity staking points are counted against. It is\nnever accepted from a request body anywhere.\n",
17965
+ "operationId": "siweLoginVerify",
17966
+ "security": [],
17967
+ "requestBody": {
17968
+ "required": true,
17969
+ "content": {
17970
+ "application/json": {
17971
+ "schema": {
17972
+ "type": "object",
17973
+ "required": [
17974
+ "message",
17975
+ "signature"
17976
+ ],
17977
+ "properties": {
17978
+ "message": {
17979
+ "type": "string",
17980
+ "description": "The challenge message, unmodified"
17981
+ },
17982
+ "signature": {
17983
+ "type": "string",
17984
+ "description": "Hex signature over the message"
17985
+ }
17986
+ }
17987
+ }
17988
+ }
17989
+ }
17990
+ },
17991
+ "responses": {
17992
+ "200": {
17993
+ "description": "Authenticated",
17994
+ "content": {
17995
+ "application/json": {
17996
+ "schema": {
17997
+ "type": "object",
17998
+ "properties": {
17999
+ "token": {
18000
+ "type": "string"
18001
+ },
18002
+ "user_id": {
18003
+ "type": "string",
18004
+ "format": "uuid"
18005
+ },
18006
+ "org_id": {
18007
+ "type": "string",
18008
+ "format": "uuid"
18009
+ },
18010
+ "wallet_address": {
18011
+ "type": "string"
18012
+ },
18013
+ "is_new_user": {
18014
+ "type": "boolean"
18015
+ },
18016
+ "email_pending": {
18017
+ "type": "boolean",
18018
+ "description": "True while the account email is still the synthetic\nwallet address. Redemption is blocked until a real\none is verified.\n"
18019
+ }
18020
+ }
18021
+ }
18022
+ }
18023
+ }
18024
+ },
18025
+ "400": {
18026
+ "description": "Expired or reused challenge, or a message signed for another domain"
18027
+ },
18028
+ "401": {
18029
+ "description": "Signature does not match the address in the message"
18030
+ }
18031
+ }
18032
+ }
18033
+ },
17677
18034
  "/v1/oauth/authorize": {
17678
18035
  "get": {
17679
18036
  "tags": [
@@ -32599,6 +32956,63 @@
32599
32956
  }
32600
32957
  },
32601
32958
  "schemas": {
32959
+ "MyReferralsResponse": {
32960
+ "type": "object",
32961
+ "required": [
32962
+ "code",
32963
+ "link",
32964
+ "total",
32965
+ "recent"
32966
+ ],
32967
+ "properties": {
32968
+ "code": {
32969
+ "type": "string",
32970
+ "description": "The caller's referral code, created on first read.",
32971
+ "example": "7f3a9c2b"
32972
+ },
32973
+ "link": {
32974
+ "type": "string",
32975
+ "format": "uri",
32976
+ "description": "The URL to share, built for the brand the request arrived on.",
32977
+ "example": "https://1claw.co/?ref=7f3a9c2b"
32978
+ },
32979
+ "total": {
32980
+ "type": "integer",
32981
+ "format": "int64",
32982
+ "description": "Countable signups attributed to this code."
32983
+ },
32984
+ "recent": {
32985
+ "type": "array",
32986
+ "items": {
32987
+ "$ref": "#/components/schemas/ReferralRow"
32988
+ }
32989
+ }
32990
+ }
32991
+ },
32992
+ "ReferralRow": {
32993
+ "type": "object",
32994
+ "required": [
32995
+ "signup_method",
32996
+ "created_at"
32997
+ ],
32998
+ "properties": {
32999
+ "signup_method": {
33000
+ "type": "string",
33001
+ "description": "How the referred person signed up.",
33002
+ "example": "email_otp"
33003
+ },
33004
+ "created_at": {
33005
+ "type": "string",
33006
+ "format": "date-time"
33007
+ },
33008
+ "referred_hint": {
33009
+ "type": "string",
33010
+ "nullable": true,
33011
+ "description": "Masked address — first character, then the domain.",
33012
+ "example": "a**@example.com"
33013
+ }
33014
+ }
33015
+ },
32602
33016
  "OtelTopology": {
32603
33017
  "type": "object",
32604
33018
  "required": [
package/openapi.yaml CHANGED
@@ -2,7 +2,7 @@ openapi: 3.1.0
2
2
 
3
3
  info:
4
4
  title: 1Claw API
5
- version: "0.61.48"
5
+ version: "0.61.50"
6
6
  description: |
7
7
  Secure secret management for AI agents. Provides vaults, secrets,
8
8
  policy-based access control, agent identity, Intents API,
@@ -4530,6 +4530,39 @@ paths:
4530
4530
  schema:
4531
4531
  $ref: "#/components/schemas/OnboardingStatus"
4532
4532
 
4533
+ /v1/referrals/me:
4534
+ get:
4535
+ tags: [Organization]
4536
+ summary: Your own referral link and signups
4537
+ description: |
4538
+ The caller's referral code, the link to share, how many signups it has
4539
+ produced, and a recent list.
4540
+
4541
+ Users only — a referral link belongs to a person, so an agent principal
4542
+ gets 403.
4543
+
4544
+ The link's host comes from the brand the request arrived on, the same
4545
+ way the SIWE domain and the WebAuthn rpId do: someone on 1claw.co must
4546
+ not be handed a 1claw.xyz link to post.
4547
+
4548
+ `recent[].referred_hint` is masked (`a**@example.com`) — enough to
4549
+ recognise someone you did invite, not enough to contact someone you did
4550
+ not. Neither the referred address nor its user id is returned.
4551
+ operationId: getMyReferrals
4552
+ responses:
4553
+ "200":
4554
+ description: The caller's referral code, link and signup count
4555
+ content:
4556
+ application/json:
4557
+ schema:
4558
+ $ref: "#/components/schemas/MyReferralsResponse"
4559
+ "403":
4560
+ description: The caller is an agent, not a person.
4561
+ content:
4562
+ application/json:
4563
+ schema:
4564
+ $ref: "#/components/schemas/ProblemDetails"
4565
+
4533
4566
  /v1/onboarding/provision:
4534
4567
  post:
4535
4568
  tags: [Organization]
@@ -5015,6 +5048,132 @@ paths:
5015
5048
  schema:
5016
5049
  $ref: "#/components/schemas/SubscriptionResponse"
5017
5050
 
5051
+ /v1/staking/points:
5052
+ get:
5053
+ tags: [Billing]
5054
+ summary: Staking points for the signed-in user's wallet
5055
+ description: |
5056
+ Points earned by staking, what has been redeemed here, and what is
5057
+ left.
5058
+
5059
+ The two halves come from different places on purpose. `earned` is
5060
+ read per request from the staking service, which recomputes it from
5061
+ on-chain events; `spent` is this service's own append-only ledger.
5062
+ `available` is the difference, floored at zero.
5063
+
5064
+ The wallet is the one on the account, proven by a SIWE signature at
5065
+ sign-in — there is no way to ask about another address.
5066
+
5067
+ `can_redeem` is false until the account has a real, verified email:
5068
+ a wallet signature proves possession of a key, not a reachable
5069
+ person, and `redeem_blocked_reason` says what to do about it.
5070
+ operationId: getStakingPoints
5071
+ responses:
5072
+ "200":
5073
+ description: Points and rates
5074
+ content:
5075
+ application/json:
5076
+ schema:
5077
+ type: object
5078
+ properties:
5079
+ wallet_address: { type: string }
5080
+ earned: { type: integer, format: int64 }
5081
+ spent: { type: integer, format: int64 }
5082
+ available: { type: integer, format: int64 }
5083
+ can_redeem: { type: boolean }
5084
+ redeem_blocked_reason:
5085
+ type: string
5086
+ nullable: true
5087
+ rates:
5088
+ type: object
5089
+ properties:
5090
+ points_per_pro_month: { type: integer }
5091
+ micro_usd_per_point: { type: integer }
5092
+ points_per_day_per_100m_tokens: { type: integer }
5093
+ max_pro_months_per_redemption: { type: integer }
5094
+ recent:
5095
+ type: array
5096
+ items:
5097
+ type: object
5098
+ properties:
5099
+ id: { type: string, format: uuid }
5100
+ wallet_address: { type: string }
5101
+ points_spent: { type: integer, format: int64 }
5102
+ reward_type:
5103
+ type: string
5104
+ enum: [pro_months, credits]
5105
+ reward_detail: { type: object }
5106
+ created_at: { type: string, format: date-time }
5107
+ "400":
5108
+ description: No wallet linked to this account
5109
+ "403":
5110
+ description: Only a signed-in person can read staking points
5111
+ "503":
5112
+ description: |
5113
+ The staking service could not report points. Deliberately not
5114
+ reported as zero — that would tell a staker their earnings
5115
+ had vanished.
5116
+
5117
+ /v1/staking/redeem:
5118
+ post:
5119
+ tags: [Billing]
5120
+ summary: Redeem staking points for plan time or credits
5121
+ description: |
5122
+ Spends points from the wallet on the account.
5123
+
5124
+ `quantity` is **months** for `pro_months` and **points** for
5125
+ `credits`; the response always states the cost actually charged.
5126
+
5127
+ Pro months extend an existing period rather than replacing it, so
5128
+ redeeming twice does not discard the time already granted. They are
5129
+ refused when the organisation has a Stripe subscription, or is on a
5130
+ tier above Pro: a comped tier would overwrite the plan being paid
5131
+ for and would never expire. Credits apply on top of a subscription
5132
+ and are the right choice there.
5133
+
5134
+ Redemption serialises on the wallet's ledger, so two concurrent
5135
+ requests cannot spend the same points.
5136
+ operationId: redeemStakingPoints
5137
+ requestBody:
5138
+ required: true
5139
+ content:
5140
+ application/json:
5141
+ schema:
5142
+ type: object
5143
+ required: [reward_type, quantity]
5144
+ properties:
5145
+ reward_type:
5146
+ type: string
5147
+ enum: [pro_months, credits]
5148
+ quantity:
5149
+ type: integer
5150
+ format: int64
5151
+ minimum: 1
5152
+ description: Months for pro_months; points for credits
5153
+ responses:
5154
+ "200":
5155
+ description: Redeemed
5156
+ content:
5157
+ application/json:
5158
+ schema:
5159
+ type: object
5160
+ properties:
5161
+ redemption_id: { type: string, format: uuid }
5162
+ points_spent: { type: integer, format: int64 }
5163
+ remaining_available: { type: integer, format: int64 }
5164
+ reward_type: { type: string }
5165
+ reward_detail: { type: object }
5166
+ "400":
5167
+ description: Not enough points, or no wallet linked
5168
+ "403":
5169
+ description: A real verified email is required before redeeming
5170
+ "409":
5171
+ description: |
5172
+ Pro months refused because the organisation's billing is owned
5173
+ by Stripe, or its tier is above Pro. Redeem credits instead.
5174
+ "503":
5175
+ description: The staking service could not report points; nothing was charged
5176
+
5018
5177
  /v1/billing/credits/topup:
5019
5178
  post:
5020
5179
  tags: [Billing]
@@ -11262,6 +11421,113 @@ paths:
11262
11421
  "429":
11263
11422
  description: Rate limited
11264
11423
 
11424
+ /v1/auth/siwe/challenge:
11425
+ post:
11426
+ tags: [Authentication]
11427
+ summary: Start wallet sign-in (SIWE)
11428
+ description: |
11429
+ Returns the exact EIP-4361 message to sign, for signing in to the
11430
+ dashboard with an Ethereum wallet.
11431
+
11432
+ The message is built server-side and returned whole: the domain and
11433
+ the nonce are ours to decide, and a client that assembles its own
11434
+ message is a client that can be talked into signing a different
11435
+ one. Sign it unmodified and post it back to
11436
+ `/v1/auth/siwe/verify`.
11437
+
11438
+ The nonce is single-use and valid for five minutes. Distinct from
11439
+ `/v1/platform/siwe/challenge`, which needs a `plt_` caller and
11440
+ issues nonces scoped to one platform app for *its* end users.
11441
+ operationId: siweLoginChallenge
11442
+ security: []
11443
+ requestBody:
11444
+ required: true
11445
+ content:
11446
+ application/json:
11447
+ schema:
11448
+ type: object
11449
+ required: [address]
11450
+ properties:
11451
+ address:
11452
+ type: string
11453
+ description: 0x-prefixed 20-byte Ethereum address
11454
+ example: "0x0000000000000000000000000000000000000001"
11455
+ responses:
11456
+ "200":
11457
+ description: Message to sign
11458
+ content:
11459
+ application/json:
11460
+ schema:
11461
+ type: object
11462
+ properties:
11463
+ message:
11464
+ type: string
11465
+ description: Sign this verbatim
11466
+ nonce: { type: string }
11467
+ expires_in_secs: { type: integer }
11468
+ "400":
11469
+ description: Not a valid Ethereum address
11470
+ "429":
11471
+ description: Rate limited
11472
+
11473
+ /v1/auth/siwe/verify:
11474
+ post:
11475
+ tags: [Authentication]
11476
+ summary: Complete wallet sign-in and get a JWT
11477
+ description: |
11478
+ Verifies the signature over the challenge message and returns an
11479
+ ordinary user JWT — the same token social login and email-OTP
11480
+ produce.
11481
+
11482
+ First sign-in for an address creates a user and org. That user's
11483
+ email starts synthetic (`email_pending: true`) and unverified: a
11484
+ wallet signature proves possession of a key, not a reachable
11485
+ person. Staking redemption refuses until a real address is added
11486
+ and confirmed.
11487
+
11488
+ The wallet recovered from the signature is stored on the account
11489
+ and is the identity staking points are counted against. It is
11490
+ never accepted from a request body anywhere.
11491
+ operationId: siweLoginVerify
11492
+ security: []
11493
+ requestBody:
11494
+ required: true
11495
+ content:
11496
+ application/json:
11497
+ schema:
11498
+ type: object
11499
+ required: [message, signature]
11500
+ properties:
11501
+ message:
11502
+ type: string
11503
+ description: The challenge message, unmodified
11504
+ signature:
11505
+ type: string
11506
+ description: Hex signature over the message
11507
+ responses:
11508
+ "200":
11509
+ description: Authenticated
11510
+ content:
11511
+ application/json:
11512
+ schema:
11513
+ type: object
11514
+ properties:
11515
+ token: { type: string }
11516
+ user_id: { type: string, format: uuid }
11517
+ org_id: { type: string, format: uuid }
11518
+ wallet_address: { type: string }
11519
+ is_new_user: { type: boolean }
11520
+ email_pending:
11521
+ type: boolean
11522
+ description: |
11523
+ True while the account email is still the synthetic
11524
+ wallet address. Redemption is blocked until a real
11525
+ one is verified.
11526
+ "400":
11527
+ description: Expired or reused challenge, or a message signed for another domain
11528
+ "401":
11529
+ description: Signature does not match the address in the message
11530
+
11265
11531
  # ---------------------------------------------------------------------------
11266
11532
  # OAuth
11267
11533
  # ---------------------------------------------------------------------------
@@ -20880,6 +21146,43 @@ components:
20880
21146
  $ref: "#/components/schemas/ProblemDetails"
20881
21147
 
20882
21148
  schemas:
21149
+ MyReferralsResponse:
21150
+ type: object
21151
+ required: [code, link, total, recent]
21152
+ properties:
21153
+ code:
21154
+ type: string
21155
+ description: The caller's referral code, created on first read.
21156
+ example: 7f3a9c2b
21157
+ link:
21158
+ type: string
21159
+ format: uri
21160
+ description: The URL to share, built for the brand the request arrived on.
21161
+ example: https://1claw.co/?ref=7f3a9c2b
21162
+ total:
21163
+ type: integer
21164
+ format: int64
21165
+ description: Countable signups attributed to this code.
21166
+ recent:
21167
+ type: array
21168
+ items:
21169
+ $ref: "#/components/schemas/ReferralRow"
21170
+ ReferralRow:
21171
+ type: object
21172
+ required: [signup_method, created_at]
21173
+ properties:
21174
+ signup_method:
21175
+ type: string
21176
+ description: How the referred person signed up.
21177
+ example: email_otp
21178
+ created_at:
21179
+ type: string
21180
+ format: date-time
21181
+ referred_hint:
21182
+ type: string
21183
+ nullable: true
21184
+ description: Masked address — first character, then the domain.
21185
+ example: a**@example.com
20883
21186
  OtelTopology:
20884
21187
  type: object
20885
21188
  required: [nodes, edges, truncated, total_nodes]
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@1claw/openapi-spec",
3
- "version": "0.61.48",
4
- "description": "OpenAPI 3.1.0 specification for the 1Claw Vault API — generate clients in any language",
3
+ "version": "0.61.50",
4
+ "description": "OpenAPI 3.1.0 specification for the 1Claw Vault API \u2014 generate clients in any language",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",