@1claw/openapi-spec 0.2.0 → 0.5.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/README.md CHANGED
@@ -44,7 +44,7 @@ import spec from "@1claw/openapi-spec/openapi.json";
44
44
 
45
45
  - **Vaults** — CRUD, CMEK enable/disable, key rotation with job tracking
46
46
  - **Secrets** — CRUD, versioning, CMEK-encrypted flag
47
- - **Agents** — CRUD with `token_ttl_seconds`, `vault_ids`, crypto proxy, transaction guardrails
47
+ - **Agents** — CRUD with `auth_method` (api_key, mtls, oidc_client_credentials), auto-generated SSH keypairs, `token_ttl_seconds`, `vault_ids`, Intents API, transaction guardrails
48
48
  - **Policies** — Glob-based access control
49
49
  - **Sharing** — Links, user/agent shares, accept/decline
50
50
  - **Billing** — Subscriptions, credits, x402
package/openapi.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "info": {
4
4
  "title": "1Claw API",
5
5
  "version": "2.1.0",
6
- "description": "Secure secret management for AI agents. Provides vaults, secrets,\npolicy-based access control, agent identity, crypto transaction proxy,\nsharing, billing, and audit logging.\n\nAll endpoints require JWT Bearer authentication unless marked with\n`security: []`.\n",
6
+ "description": "Secure secret management for AI agents. Provides vaults, secrets,\npolicy-based access control, agent identity, Intents API,\nsharing, billing, and audit logging.\n\nAll endpoints require JWT Bearer authentication unless marked with\n`security: []`.\n",
7
7
  "contact": {
8
8
  "email": "ops@1claw.xyz"
9
9
  }
@@ -50,7 +50,7 @@
50
50
  },
51
51
  {
52
52
  "name": "Transactions",
53
- "description": "Crypto transaction proxy (signing, simulation)"
53
+ "description": "Intents API (signing, simulation)"
54
54
  },
55
55
  {
56
56
  "name": "Chains",
@@ -389,6 +389,93 @@
389
389
  }
390
390
  }
391
391
  },
392
+ "/v1/auth/me": {
393
+ "get": {
394
+ "tags": [
395
+ "Authentication"
396
+ ],
397
+ "summary": "Get current user profile",
398
+ "operationId": "getMe",
399
+ "responses": {
400
+ "200": {
401
+ "description": "User profile",
402
+ "content": {
403
+ "application/json": {
404
+ "schema": {
405
+ "$ref": "#/components/schemas/UserProfileResponse"
406
+ }
407
+ }
408
+ }
409
+ }
410
+ }
411
+ },
412
+ "patch": {
413
+ "tags": [
414
+ "Authentication"
415
+ ],
416
+ "summary": "Update user profile",
417
+ "operationId": "updateMe",
418
+ "requestBody": {
419
+ "required": true,
420
+ "content": {
421
+ "application/json": {
422
+ "schema": {
423
+ "$ref": "#/components/schemas/UpdateProfileRequest"
424
+ }
425
+ }
426
+ }
427
+ },
428
+ "responses": {
429
+ "200": {
430
+ "description": "Profile updated",
431
+ "content": {
432
+ "application/json": {
433
+ "schema": {
434
+ "$ref": "#/components/schemas/UserProfileResponse"
435
+ }
436
+ }
437
+ }
438
+ },
439
+ "400": {
440
+ "$ref": "#/components/responses/BadRequest"
441
+ }
442
+ }
443
+ },
444
+ "delete": {
445
+ "tags": [
446
+ "Authentication"
447
+ ],
448
+ "summary": "Delete current user account",
449
+ "operationId": "deleteMe",
450
+ "requestBody": {
451
+ "required": true,
452
+ "content": {
453
+ "application/json": {
454
+ "schema": {
455
+ "type": "object",
456
+ "required": [
457
+ "confirmation"
458
+ ],
459
+ "properties": {
460
+ "confirmation": {
461
+ "type": "string",
462
+ "description": "Must be \"DELETE MY ACCOUNT\""
463
+ }
464
+ }
465
+ }
466
+ }
467
+ }
468
+ },
469
+ "responses": {
470
+ "204": {
471
+ "description": "Account deleted"
472
+ },
473
+ "400": {
474
+ "$ref": "#/components/responses/BadRequest"
475
+ }
476
+ }
477
+ }
478
+ },
392
479
  "/v1/auth/mfa/status": {
393
480
  "get": {
394
481
  "tags": [
@@ -1280,6 +1367,41 @@
1280
1367
  }
1281
1368
  }
1282
1369
  },
1370
+ "/v1/agents/enroll": {
1371
+ "post": {
1372
+ "tags": [
1373
+ "Agents"
1374
+ ],
1375
+ "summary": "Self-enroll an agent",
1376
+ "operationId": "enrollAgent",
1377
+ "description": "Public endpoint (no auth required). Creates an agent under the human's org\nand emails the credentials to the specified human email. The API key is NOT\nreturned in the response. Anti-spam: IP rate limiting + per-email cooldown.\n",
1378
+ "requestBody": {
1379
+ "required": true,
1380
+ "content": {
1381
+ "application/json": {
1382
+ "schema": {
1383
+ "$ref": "#/components/schemas/EnrollAgentRequest"
1384
+ }
1385
+ }
1386
+ }
1387
+ },
1388
+ "responses": {
1389
+ "201": {
1390
+ "description": "Enrollment processed (uniform response to prevent email enumeration)",
1391
+ "content": {
1392
+ "application/json": {
1393
+ "schema": {
1394
+ "$ref": "#/components/schemas/EnrollAgentResponse"
1395
+ }
1396
+ }
1397
+ }
1398
+ },
1399
+ "429": {
1400
+ "description": "Rate limit exceeded"
1401
+ }
1402
+ }
1403
+ }
1404
+ },
1283
1405
  "/v1/agents": {
1284
1406
  "post": {
1285
1407
  "tags": [
@@ -1478,10 +1600,20 @@
1478
1600
  "Transactions"
1479
1601
  ],
1480
1602
  "summary": "Submit a transaction for signing",
1603
+ "description": "Replay protection: send an optional **Idempotency-Key** header (e.g. UUID or opaque string).\nDuplicate requests with the same key within 24 hours return the cached transaction response\n(no second sign/broadcast). Omit the header for non-idempotent submissions.\n",
1481
1604
  "operationId": "submitTransaction",
1482
1605
  "parameters": [
1483
1606
  {
1484
1607
  "$ref": "#/components/parameters/AgentId"
1608
+ },
1609
+ {
1610
+ "name": "Idempotency-Key",
1611
+ "in": "header",
1612
+ "required": false,
1613
+ "description": "Optional key for replay protection; duplicate requests return cached response.",
1614
+ "schema": {
1615
+ "type": "string"
1616
+ }
1485
1617
  }
1486
1618
  ],
1487
1619
  "requestBody": {
@@ -1495,6 +1627,16 @@
1495
1627
  }
1496
1628
  },
1497
1629
  "responses": {
1630
+ "200": {
1631
+ "description": "Transaction previously created with same Idempotency-Key (replay-safe response)",
1632
+ "content": {
1633
+ "application/json": {
1634
+ "schema": {
1635
+ "$ref": "#/components/schemas/TransactionResponse"
1636
+ }
1637
+ }
1638
+ }
1639
+ },
1498
1640
  "201": {
1499
1641
  "description": "Transaction signed (and optionally broadcast)",
1500
1642
  "content": {
@@ -1508,6 +1650,16 @@
1508
1650
  "403": {
1509
1651
  "$ref": "#/components/responses/Forbidden"
1510
1652
  },
1653
+ "409": {
1654
+ "description": "Idempotency-Key in use by another in-flight request; retry later.",
1655
+ "content": {
1656
+ "application/json": {
1657
+ "schema": {
1658
+ "$ref": "#/components/schemas/ProblemDetails"
1659
+ }
1660
+ }
1661
+ }
1662
+ },
1511
1663
  "422": {
1512
1664
  "description": "Simulation reverted (when simulate_first is true)",
1513
1665
  "content": {
@@ -1529,6 +1681,9 @@
1529
1681
  "parameters": [
1530
1682
  {
1531
1683
  "$ref": "#/components/parameters/AgentId"
1684
+ },
1685
+ {
1686
+ "$ref": "#/components/parameters/IncludeSignedTx"
1532
1687
  }
1533
1688
  ],
1534
1689
  "responses": {
@@ -1564,6 +1719,9 @@
1564
1719
  "type": "string",
1565
1720
  "format": "uuid"
1566
1721
  }
1722
+ },
1723
+ {
1724
+ "$ref": "#/components/parameters/IncludeSignedTx"
1567
1725
  }
1568
1726
  ],
1569
1727
  "responses": {
@@ -2818,6 +2976,48 @@
2818
2976
  }
2819
2977
  }
2820
2978
  },
2979
+ "/v1/admin/orgs/{org_id}/billing-tier": {
2980
+ "put": {
2981
+ "tags": [
2982
+ "Admin"
2983
+ ],
2984
+ "summary": "Set org billing tier (without Stripe)",
2985
+ "operationId": "adminSetBillingTier",
2986
+ "description": "Manually set an organization's billing tier to free, pro, or business.\nFor testing and manual upgrades — does not create a Stripe subscription.\nSetting to \"pro\" or \"business\" sets period_end to +1 year.\nSetting to \"free\" clears subscription data.\n",
2987
+ "parameters": [
2988
+ {
2989
+ "name": "org_id",
2990
+ "in": "path",
2991
+ "required": true,
2992
+ "schema": {
2993
+ "type": "string",
2994
+ "format": "uuid"
2995
+ }
2996
+ }
2997
+ ],
2998
+ "requestBody": {
2999
+ "required": true,
3000
+ "content": {
3001
+ "application/json": {
3002
+ "schema": {
3003
+ "$ref": "#/components/schemas/SetBillingTierRequest"
3004
+ }
3005
+ }
3006
+ }
3007
+ },
3008
+ "responses": {
3009
+ "200": {
3010
+ "description": "Billing tier updated"
3011
+ },
3012
+ "400": {
3013
+ "$ref": "#/components/responses/BadRequest"
3014
+ },
3015
+ "403": {
3016
+ "$ref": "#/components/responses/Forbidden"
3017
+ }
3018
+ }
3019
+ }
3020
+ },
2821
3021
  "/v1/health": {
2822
3022
  "get": {
2823
3023
  "tags": [
@@ -2922,6 +3122,16 @@
2922
3122
  "type": "string",
2923
3123
  "format": "uuid"
2924
3124
  }
3125
+ },
3126
+ "IncludeSignedTx": {
3127
+ "name": "include_signed_tx",
3128
+ "in": "query",
3129
+ "required": false,
3130
+ "description": "Set to `true` to include the raw signed transaction hex in the response. Omitted by default to reduce key exfiltration risk.\n",
3131
+ "schema": {
3132
+ "type": "boolean",
3133
+ "default": false
3134
+ }
2925
3135
  }
2926
3136
  },
2927
3137
  "responses": {
@@ -3297,6 +3507,51 @@
3297
3507
  }
3298
3508
  }
3299
3509
  },
3510
+ "UserProfileResponse": {
3511
+ "type": "object",
3512
+ "properties": {
3513
+ "id": {
3514
+ "type": "string",
3515
+ "format": "uuid"
3516
+ },
3517
+ "email": {
3518
+ "type": "string"
3519
+ },
3520
+ "display_name": {
3521
+ "type": "string"
3522
+ },
3523
+ "auth_method": {
3524
+ "type": "string"
3525
+ },
3526
+ "role": {
3527
+ "type": "string"
3528
+ },
3529
+ "email_verified": {
3530
+ "type": "boolean"
3531
+ },
3532
+ "marketing_emails": {
3533
+ "type": "boolean"
3534
+ },
3535
+ "totp_enabled": {
3536
+ "type": "boolean"
3537
+ },
3538
+ "created_at": {
3539
+ "type": "string",
3540
+ "format": "date-time"
3541
+ }
3542
+ }
3543
+ },
3544
+ "UpdateProfileRequest": {
3545
+ "type": "object",
3546
+ "properties": {
3547
+ "display_name": {
3548
+ "type": "string"
3549
+ },
3550
+ "marketing_emails": {
3551
+ "type": "boolean"
3552
+ }
3553
+ }
3554
+ },
3300
3555
  "CreateApiKeyRequest": {
3301
3556
  "type": "object",
3302
3557
  "required": [
@@ -3771,6 +4026,42 @@
3771
4026
  }
3772
4027
  }
3773
4028
  },
4029
+ "EnrollAgentRequest": {
4030
+ "type": "object",
4031
+ "required": [
4032
+ "name",
4033
+ "human_email"
4034
+ ],
4035
+ "properties": {
4036
+ "name": {
4037
+ "type": "string",
4038
+ "description": "Display name for the new agent"
4039
+ },
4040
+ "human_email": {
4041
+ "type": "string",
4042
+ "format": "email",
4043
+ "description": "Email of the human who will receive the agent credentials"
4044
+ },
4045
+ "description": {
4046
+ "type": "string",
4047
+ "description": "Optional agent description"
4048
+ }
4049
+ }
4050
+ },
4051
+ "EnrollAgentResponse": {
4052
+ "type": "object",
4053
+ "properties": {
4054
+ "agent_id": {
4055
+ "type": "string",
4056
+ "format": "uuid",
4057
+ "description": "UUID of the created agent (nil UUID when email not found — uniform response)"
4058
+ },
4059
+ "message": {
4060
+ "type": "string",
4061
+ "description": "Status message (always generic to prevent email enumeration)"
4062
+ }
4063
+ }
4064
+ },
3774
4065
  "CreateAgentRequest": {
3775
4066
  "type": "object",
3776
4067
  "required": [
@@ -3784,7 +4075,14 @@
3784
4075
  "type": "string"
3785
4076
  },
3786
4077
  "auth_method": {
3787
- "type": "string"
4078
+ "type": "string",
4079
+ "enum": [
4080
+ "api_key",
4081
+ "mtls",
4082
+ "oidc_client_credentials"
4083
+ ],
4084
+ "default": "api_key",
4085
+ "description": "Authentication method. api_key generates a one-time key; mtls requires client_cert_fingerprint; oidc_client_credentials requires oidc_issuer and oidc_client_id."
3788
4086
  },
3789
4087
  "scopes": {
3790
4088
  "type": "array",
@@ -3796,7 +4094,7 @@
3796
4094
  "type": "string",
3797
4095
  "format": "date-time"
3798
4096
  },
3799
- "crypto_proxy_enabled": {
4097
+ "intents_api_enabled": {
3800
4098
  "type": "boolean",
3801
4099
  "default": false
3802
4100
  },
@@ -3830,6 +4128,18 @@
3830
4128
  "format": "uuid"
3831
4129
  },
3832
4130
  "description": "Restrict agent to specific vault UUIDs (empty = all vaults in org)"
4131
+ },
4132
+ "client_cert_fingerprint": {
4133
+ "type": "string",
4134
+ "description": "SHA-256 fingerprint of the client certificate (required for mTLS auth)"
4135
+ },
4136
+ "oidc_issuer": {
4137
+ "type": "string",
4138
+ "description": "OIDC issuer URL (required for oidc_client_credentials auth)"
4139
+ },
4140
+ "oidc_client_id": {
4141
+ "type": "string",
4142
+ "description": "OIDC client ID (required for oidc_client_credentials auth)"
3833
4143
  }
3834
4144
  }
3835
4145
  },
@@ -3852,7 +4162,7 @@
3852
4162
  "type": "string",
3853
4163
  "format": "date-time"
3854
4164
  },
3855
- "crypto_proxy_enabled": {
4165
+ "intents_api_enabled": {
3856
4166
  "type": "boolean"
3857
4167
  },
3858
4168
  "tx_to_allowlist": {
@@ -3893,7 +4203,7 @@
3893
4203
  "name",
3894
4204
  "auth_method",
3895
4205
  "is_active",
3896
- "crypto_proxy_enabled",
4206
+ "intents_api_enabled",
3897
4207
  "created_at"
3898
4208
  ],
3899
4209
  "properties": {
@@ -3908,7 +4218,12 @@
3908
4218
  "type": "string"
3909
4219
  },
3910
4220
  "auth_method": {
3911
- "type": "string"
4221
+ "type": "string",
4222
+ "enum": [
4223
+ "api_key",
4224
+ "mtls",
4225
+ "oidc_client_credentials"
4226
+ ]
3912
4227
  },
3913
4228
  "scopes": {
3914
4229
  "type": "array",
@@ -3919,7 +4234,7 @@
3919
4234
  "is_active": {
3920
4235
  "type": "boolean"
3921
4236
  },
3922
- "crypto_proxy_enabled": {
4237
+ "intents_api_enabled": {
3923
4238
  "type": "boolean"
3924
4239
  },
3925
4240
  "tx_to_allowlist": {
@@ -3951,6 +4266,26 @@
3951
4266
  "format": "uuid"
3952
4267
  }
3953
4268
  },
4269
+ "client_cert_fingerprint": {
4270
+ "type": "string",
4271
+ "description": "SHA-256 fingerprint of the client certificate (mTLS agents)"
4272
+ },
4273
+ "oidc_issuer": {
4274
+ "type": "string",
4275
+ "description": "OIDC issuer URL (oidc_client_credentials agents)"
4276
+ },
4277
+ "oidc_client_id": {
4278
+ "type": "string",
4279
+ "description": "OIDC client ID (oidc_client_credentials agents)"
4280
+ },
4281
+ "ssh_public_key": {
4282
+ "type": "string",
4283
+ "description": "Ed25519 SSH public key (base64-encoded, auto-generated at creation)"
4284
+ },
4285
+ "ecdh_public_key": {
4286
+ "type": "string",
4287
+ "description": "P-256 ECDH public key (base64 SEC1 uncompressed point, auto-generated at creation)"
4288
+ },
3954
4289
  "created_at": {
3955
4290
  "type": "string",
3956
4291
  "format": "date-time"
@@ -3991,7 +4326,7 @@
3991
4326
  "is_active": {
3992
4327
  "type": "boolean"
3993
4328
  },
3994
- "crypto_proxy_enabled": {
4329
+ "intents_api_enabled": {
3995
4330
  "type": "boolean"
3996
4331
  },
3997
4332
  "created_by": {
@@ -4009,14 +4344,21 @@
4009
4344
  "last_active_at": {
4010
4345
  "type": "string",
4011
4346
  "format": "date-time"
4347
+ },
4348
+ "ssh_public_key": {
4349
+ "type": "string",
4350
+ "description": "Ed25519 SSH public key (base64-encoded)"
4351
+ },
4352
+ "ecdh_public_key": {
4353
+ "type": "string",
4354
+ "description": "P-256 ECDH public key (base64 SEC1 uncompressed point)"
4012
4355
  }
4013
4356
  }
4014
4357
  },
4015
4358
  "AgentCreatedResponse": {
4016
4359
  "type": "object",
4017
4360
  "required": [
4018
- "agent",
4019
- "api_key"
4361
+ "agent"
4020
4362
  ],
4021
4363
  "properties": {
4022
4364
  "agent": {
@@ -4024,7 +4366,7 @@
4024
4366
  },
4025
4367
  "api_key": {
4026
4368
  "type": "string",
4027
- "description": "One-time API key (store securely)"
4369
+ "description": "One-time API key (only present for api_key auth method)"
4028
4370
  }
4029
4371
  }
4030
4372
  },
@@ -4171,7 +4513,9 @@
4171
4513
  ]
4172
4514
  },
4173
4515
  "signed_tx": {
4174
- "type": "string"
4516
+ "type": "string",
4517
+ "nullable": true,
4518
+ "description": "Raw signed transaction hex. Omitted (null) by default to reduce exfiltration risk. Pass `include_signed_tx=true` query param on GET endpoints to include it. Always returned on the initial POST submission response.\n"
4175
4519
  },
4176
4520
  "tx_hash": {
4177
4521
  "type": "string"
@@ -4831,7 +5175,7 @@
4831
5175
  "team_members": {
4832
5176
  "$ref": "#/components/schemas/UsageMeter"
4833
5177
  },
4834
- "proxy_transactions": {
5178
+ "intent_transactions": {
4835
5179
  "$ref": "#/components/schemas/UsageMeter"
4836
5180
  },
4837
5181
  "shares": {
@@ -5134,6 +5478,9 @@
5134
5478
  "org_name": {
5135
5479
  "type": "string"
5136
5480
  },
5481
+ "billing_tier": {
5482
+ "type": "string"
5483
+ },
5137
5484
  "created_at": {
5138
5485
  "type": "string",
5139
5486
  "format": "date-time"
@@ -5181,6 +5528,22 @@
5181
5528
  }
5182
5529
  }
5183
5530
  },
5531
+ "SetBillingTierRequest": {
5532
+ "type": "object",
5533
+ "required": [
5534
+ "tier"
5535
+ ],
5536
+ "properties": {
5537
+ "tier": {
5538
+ "type": "string",
5539
+ "enum": [
5540
+ "free",
5541
+ "pro",
5542
+ "business"
5543
+ ]
5544
+ }
5545
+ }
5546
+ },
5184
5547
  "PaymentRequirement": {
5185
5548
  "type": "object",
5186
5549
  "properties": {
package/openapi.yaml CHANGED
@@ -5,7 +5,7 @@ info:
5
5
  version: 2.1.0
6
6
  description: |
7
7
  Secure secret management for AI agents. Provides vaults, secrets,
8
- policy-based access control, agent identity, crypto transaction proxy,
8
+ policy-based access control, agent identity, Intents API,
9
9
  sharing, billing, and audit logging.
10
10
 
11
11
  All endpoints require JWT Bearer authentication unless marked with
@@ -36,7 +36,7 @@ tags:
36
36
  - name: Agents
37
37
  description: Agent identity and key management
38
38
  - name: Transactions
39
- description: Crypto transaction proxy (signing, simulation)
39
+ description: Intents API (signing, simulation)
40
40
  - name: Chains
41
41
  description: Blockchain chain registry
42
42
  - name: Sharing
@@ -252,6 +252,58 @@ paths:
252
252
  "400":
253
253
  $ref: "#/components/responses/BadRequest"
254
254
 
255
+ /v1/auth/me:
256
+ get:
257
+ tags: [Authentication]
258
+ summary: Get current user profile
259
+ operationId: getMe
260
+ responses:
261
+ "200":
262
+ description: User profile
263
+ content:
264
+ application/json:
265
+ schema:
266
+ $ref: "#/components/schemas/UserProfileResponse"
267
+ patch:
268
+ tags: [Authentication]
269
+ summary: Update user profile
270
+ operationId: updateMe
271
+ requestBody:
272
+ required: true
273
+ content:
274
+ application/json:
275
+ schema:
276
+ $ref: "#/components/schemas/UpdateProfileRequest"
277
+ responses:
278
+ "200":
279
+ description: Profile updated
280
+ content:
281
+ application/json:
282
+ schema:
283
+ $ref: "#/components/schemas/UserProfileResponse"
284
+ "400":
285
+ $ref: "#/components/responses/BadRequest"
286
+ delete:
287
+ tags: [Authentication]
288
+ summary: Delete current user account
289
+ operationId: deleteMe
290
+ requestBody:
291
+ required: true
292
+ content:
293
+ application/json:
294
+ schema:
295
+ type: object
296
+ required: [confirmation]
297
+ properties:
298
+ confirmation:
299
+ type: string
300
+ description: Must be "DELETE MY ACCOUNT"
301
+ responses:
302
+ "204":
303
+ description: Account deleted
304
+ "400":
305
+ $ref: "#/components/responses/BadRequest"
306
+
255
307
  # MFA
256
308
 
257
309
  /v1/auth/mfa/status:
@@ -816,6 +868,35 @@ paths:
816
868
  "404":
817
869
  $ref: "#/components/responses/NotFound"
818
870
 
871
+ # ---------------------------------------------------------------------------
872
+ # Agent Self-Enrollment (public)
873
+ # ---------------------------------------------------------------------------
874
+
875
+ /v1/agents/enroll:
876
+ post:
877
+ tags: [Agents]
878
+ summary: Self-enroll an agent
879
+ operationId: enrollAgent
880
+ description: |
881
+ Public endpoint (no auth required). Creates an agent under the human's org
882
+ and emails the credentials to the specified human email. The API key is NOT
883
+ returned in the response. Anti-spam: IP rate limiting + per-email cooldown.
884
+ requestBody:
885
+ required: true
886
+ content:
887
+ application/json:
888
+ schema:
889
+ $ref: "#/components/schemas/EnrollAgentRequest"
890
+ responses:
891
+ "201":
892
+ description: Enrollment processed (uniform response to prevent email enumeration)
893
+ content:
894
+ application/json:
895
+ schema:
896
+ $ref: "#/components/schemas/EnrollAgentResponse"
897
+ "429":
898
+ description: Rate limit exceeded
899
+
819
900
  # ---------------------------------------------------------------------------
820
901
  # Agents
821
902
  # ---------------------------------------------------------------------------
@@ -934,16 +1015,26 @@ paths:
934
1015
  $ref: "#/components/responses/NotFound"
935
1016
 
936
1017
  # ---------------------------------------------------------------------------
937
- # Transactions (Crypto Proxy)
1018
+ # Transactions (Intents API)
938
1019
  # ---------------------------------------------------------------------------
939
1020
 
940
1021
  /v1/agents/{agent_id}/transactions:
941
1022
  post:
942
1023
  tags: [Transactions]
943
1024
  summary: Submit a transaction for signing
1025
+ description: |
1026
+ Replay protection: send an optional **Idempotency-Key** header (e.g. UUID or opaque string).
1027
+ Duplicate requests with the same key within 24 hours return the cached transaction response
1028
+ (no second sign/broadcast). Omit the header for non-idempotent submissions.
944
1029
  operationId: submitTransaction
945
1030
  parameters:
946
1031
  - $ref: "#/components/parameters/AgentId"
1032
+ - name: Idempotency-Key
1033
+ in: header
1034
+ required: false
1035
+ description: Optional key for replay protection; duplicate requests return cached response.
1036
+ schema:
1037
+ type: string
947
1038
  requestBody:
948
1039
  required: true
949
1040
  content:
@@ -957,8 +1048,20 @@ paths:
957
1048
  application/json:
958
1049
  schema:
959
1050
  $ref: "#/components/schemas/TransactionResponse"
1051
+ "200":
1052
+ description: Transaction previously created with same Idempotency-Key (replay-safe response)
1053
+ content:
1054
+ application/json:
1055
+ schema:
1056
+ $ref: "#/components/schemas/TransactionResponse"
960
1057
  "403":
961
1058
  $ref: "#/components/responses/Forbidden"
1059
+ "409":
1060
+ description: Idempotency-Key in use by another in-flight request; retry later.
1061
+ content:
1062
+ application/json:
1063
+ schema:
1064
+ $ref: "#/components/schemas/ProblemDetails"
962
1065
  "422":
963
1066
  description: Simulation reverted (when simulate_first is true)
964
1067
  content:
@@ -971,6 +1074,7 @@ paths:
971
1074
  operationId: listTransactions
972
1075
  parameters:
973
1076
  - $ref: "#/components/parameters/AgentId"
1077
+ - $ref: "#/components/parameters/IncludeSignedTx"
974
1078
  responses:
975
1079
  "200":
976
1080
  description: Transaction list
@@ -992,6 +1096,7 @@ paths:
992
1096
  schema:
993
1097
  type: string
994
1098
  format: uuid
1099
+ - $ref: "#/components/parameters/IncludeSignedTx"
995
1100
  responses:
996
1101
  "200":
997
1102
  description: Transaction details
@@ -1790,6 +1895,37 @@ paths:
1790
1895
  schema:
1791
1896
  $ref: "#/components/schemas/OrgLimitsResponse"
1792
1897
 
1898
+ /v1/admin/orgs/{org_id}/billing-tier:
1899
+ put:
1900
+ tags: [Admin]
1901
+ summary: Set org billing tier (without Stripe)
1902
+ operationId: adminSetBillingTier
1903
+ description: |
1904
+ Manually set an organization's billing tier to free, pro, or business.
1905
+ For testing and manual upgrades — does not create a Stripe subscription.
1906
+ Setting to "pro" or "business" sets period_end to +1 year.
1907
+ Setting to "free" clears subscription data.
1908
+ parameters:
1909
+ - name: org_id
1910
+ in: path
1911
+ required: true
1912
+ schema:
1913
+ type: string
1914
+ format: uuid
1915
+ requestBody:
1916
+ required: true
1917
+ content:
1918
+ application/json:
1919
+ schema:
1920
+ $ref: "#/components/schemas/SetBillingTierRequest"
1921
+ responses:
1922
+ "200":
1923
+ description: Billing tier updated
1924
+ "400":
1925
+ $ref: "#/components/responses/BadRequest"
1926
+ "403":
1927
+ $ref: "#/components/responses/Forbidden"
1928
+
1793
1929
  # ---------------------------------------------------------------------------
1794
1930
  # Health
1795
1931
  # ---------------------------------------------------------------------------
@@ -1871,6 +2007,16 @@ components:
1871
2007
  schema:
1872
2008
  type: string
1873
2009
  format: uuid
2010
+ IncludeSignedTx:
2011
+ name: include_signed_tx
2012
+ in: query
2013
+ required: false
2014
+ description: >
2015
+ Set to `true` to include the raw signed transaction hex in the response.
2016
+ Omitted by default to reduce key exfiltration risk.
2017
+ schema:
2018
+ type: boolean
2019
+ default: false
1874
2020
 
1875
2021
  responses:
1876
2022
  BadRequest:
@@ -2125,6 +2271,38 @@ components:
2125
2271
  user_code:
2126
2272
  type: string
2127
2273
 
2274
+ UserProfileResponse:
2275
+ type: object
2276
+ properties:
2277
+ id:
2278
+ type: string
2279
+ format: uuid
2280
+ email:
2281
+ type: string
2282
+ display_name:
2283
+ type: string
2284
+ auth_method:
2285
+ type: string
2286
+ role:
2287
+ type: string
2288
+ email_verified:
2289
+ type: boolean
2290
+ marketing_emails:
2291
+ type: boolean
2292
+ totp_enabled:
2293
+ type: boolean
2294
+ created_at:
2295
+ type: string
2296
+ format: date-time
2297
+
2298
+ UpdateProfileRequest:
2299
+ type: object
2300
+ properties:
2301
+ display_name:
2302
+ type: string
2303
+ marketing_emails:
2304
+ type: boolean
2305
+
2128
2306
  # --- API Keys ---
2129
2307
 
2130
2308
  CreateApiKeyRequest:
@@ -2444,6 +2622,34 @@ components:
2444
2622
  items:
2445
2623
  $ref: "#/components/schemas/PolicyResponse"
2446
2624
 
2625
+ # --- Agent Enrollment ---
2626
+
2627
+ EnrollAgentRequest:
2628
+ type: object
2629
+ required: [name, human_email]
2630
+ properties:
2631
+ name:
2632
+ type: string
2633
+ description: Display name for the new agent
2634
+ human_email:
2635
+ type: string
2636
+ format: email
2637
+ description: Email of the human who will receive the agent credentials
2638
+ description:
2639
+ type: string
2640
+ description: Optional agent description
2641
+
2642
+ EnrollAgentResponse:
2643
+ type: object
2644
+ properties:
2645
+ agent_id:
2646
+ type: string
2647
+ format: uuid
2648
+ description: UUID of the created agent (nil UUID when email not found — uniform response)
2649
+ message:
2650
+ type: string
2651
+ description: Status message (always generic to prevent email enumeration)
2652
+
2447
2653
  # --- Agents ---
2448
2654
 
2449
2655
  CreateAgentRequest:
@@ -2456,6 +2662,9 @@ components:
2456
2662
  type: string
2457
2663
  auth_method:
2458
2664
  type: string
2665
+ enum: [api_key, mtls, oidc_client_credentials]
2666
+ default: api_key
2667
+ description: Authentication method. api_key generates a one-time key; mtls requires client_cert_fingerprint; oidc_client_credentials requires oidc_issuer and oidc_client_id.
2459
2668
  scopes:
2460
2669
  type: array
2461
2670
  items:
@@ -2463,7 +2672,7 @@ components:
2463
2672
  expires_at:
2464
2673
  type: string
2465
2674
  format: date-time
2466
- crypto_proxy_enabled:
2675
+ intents_api_enabled:
2467
2676
  type: boolean
2468
2677
  default: false
2469
2678
  tx_to_allowlist:
@@ -2488,6 +2697,15 @@ components:
2488
2697
  type: string
2489
2698
  format: uuid
2490
2699
  description: Restrict agent to specific vault UUIDs (empty = all vaults in org)
2700
+ client_cert_fingerprint:
2701
+ type: string
2702
+ description: SHA-256 fingerprint of the client certificate (required for mTLS auth)
2703
+ oidc_issuer:
2704
+ type: string
2705
+ description: OIDC issuer URL (required for oidc_client_credentials auth)
2706
+ oidc_client_id:
2707
+ type: string
2708
+ description: OIDC client ID (required for oidc_client_credentials auth)
2491
2709
 
2492
2710
  UpdateAgentRequest:
2493
2711
  type: object
@@ -2503,7 +2721,7 @@ components:
2503
2721
  expires_at:
2504
2722
  type: string
2505
2723
  format: date-time
2506
- crypto_proxy_enabled:
2724
+ intents_api_enabled:
2507
2725
  type: boolean
2508
2726
  tx_to_allowlist:
2509
2727
  type: array
@@ -2528,7 +2746,7 @@ components:
2528
2746
 
2529
2747
  AgentResponse:
2530
2748
  type: object
2531
- required: [id, name, auth_method, is_active, crypto_proxy_enabled, created_at]
2749
+ required: [id, name, auth_method, is_active, intents_api_enabled, created_at]
2532
2750
  properties:
2533
2751
  id:
2534
2752
  type: string
@@ -2539,13 +2757,14 @@ components:
2539
2757
  type: string
2540
2758
  auth_method:
2541
2759
  type: string
2760
+ enum: [api_key, mtls, oidc_client_credentials]
2542
2761
  scopes:
2543
2762
  type: array
2544
2763
  items:
2545
2764
  type: string
2546
2765
  is_active:
2547
2766
  type: boolean
2548
- crypto_proxy_enabled:
2767
+ intents_api_enabled:
2549
2768
  type: boolean
2550
2769
  tx_to_allowlist:
2551
2770
  type: array
@@ -2567,6 +2786,21 @@ components:
2567
2786
  items:
2568
2787
  type: string
2569
2788
  format: uuid
2789
+ client_cert_fingerprint:
2790
+ type: string
2791
+ description: SHA-256 fingerprint of the client certificate (mTLS agents)
2792
+ oidc_issuer:
2793
+ type: string
2794
+ description: OIDC issuer URL (oidc_client_credentials agents)
2795
+ oidc_client_id:
2796
+ type: string
2797
+ description: OIDC client ID (oidc_client_credentials agents)
2798
+ ssh_public_key:
2799
+ type: string
2800
+ description: Ed25519 SSH public key (base64-encoded, auto-generated at creation)
2801
+ ecdh_public_key:
2802
+ type: string
2803
+ description: P-256 ECDH public key (base64 SEC1 uncompressed point, auto-generated at creation)
2570
2804
  created_at:
2571
2805
  type: string
2572
2806
  format: date-time
@@ -2596,7 +2830,7 @@ components:
2596
2830
  type: string
2597
2831
  is_active:
2598
2832
  type: boolean
2599
- crypto_proxy_enabled:
2833
+ intents_api_enabled:
2600
2834
  type: boolean
2601
2835
  created_by:
2602
2836
  type: string
@@ -2610,16 +2844,22 @@ components:
2610
2844
  last_active_at:
2611
2845
  type: string
2612
2846
  format: date-time
2847
+ ssh_public_key:
2848
+ type: string
2849
+ description: Ed25519 SSH public key (base64-encoded)
2850
+ ecdh_public_key:
2851
+ type: string
2852
+ description: P-256 ECDH public key (base64 SEC1 uncompressed point)
2613
2853
 
2614
2854
  AgentCreatedResponse:
2615
2855
  type: object
2616
- required: [agent, api_key]
2856
+ required: [agent]
2617
2857
  properties:
2618
2858
  agent:
2619
2859
  $ref: "#/components/schemas/AgentResponse"
2620
2860
  api_key:
2621
2861
  type: string
2622
- description: One-time API key (store securely)
2862
+ description: One-time API key (only present for api_key auth method)
2623
2863
 
2624
2864
  AgentListResponse:
2625
2865
  type: object
@@ -2717,6 +2957,11 @@ components:
2717
2957
  enum: [pending, signed, broadcast, failed, simulation_failed]
2718
2958
  signed_tx:
2719
2959
  type: string
2960
+ nullable: true
2961
+ description: >
2962
+ Raw signed transaction hex. Omitted (null) by default to reduce exfiltration risk.
2963
+ Pass `include_signed_tx=true` query param on GET endpoints to include it.
2964
+ Always returned on the initial POST submission response.
2720
2965
  tx_hash:
2721
2966
  type: string
2722
2967
  error_message:
@@ -3169,7 +3414,7 @@ components:
3169
3414
  $ref: "#/components/schemas/UsageMeter"
3170
3415
  team_members:
3171
3416
  $ref: "#/components/schemas/UsageMeter"
3172
- proxy_transactions:
3417
+ intent_transactions:
3173
3418
  $ref: "#/components/schemas/UsageMeter"
3174
3419
  shares:
3175
3420
  $ref: "#/components/schemas/UsageMeter"
@@ -3386,6 +3631,8 @@ components:
3386
3631
  format: uuid
3387
3632
  org_name:
3388
3633
  type: string
3634
+ billing_tier:
3635
+ type: string
3389
3636
  created_at:
3390
3637
  type: string
3391
3638
  format: date-time
@@ -3417,6 +3664,14 @@ components:
3417
3664
  is_sponsored:
3418
3665
  type: boolean
3419
3666
 
3667
+ SetBillingTierRequest:
3668
+ type: object
3669
+ required: [tier]
3670
+ properties:
3671
+ tier:
3672
+ type: string
3673
+ enum: [free, pro, business]
3674
+
3420
3675
  # --- x402 ---
3421
3676
 
3422
3677
  PaymentRequirement:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1claw/openapi-spec",
3
- "version": "0.2.0",
3
+ "version": "0.5.0",
4
4
  "description": "OpenAPI 3.1.0 specification for the 1Claw Vault API — generate clients in any language",
5
5
  "license": "PolyForm-Noncommercial-1.0.0",
6
6
  "repository": {