@primitivedotdev/sdk 1.5.0 → 1.7.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.
@@ -73,6 +73,10 @@ const openapiDocument = {
73
73
  "name": "Filters",
74
74
  "description": "Manage whitelist and blocklist filter rules"
75
75
  },
76
+ {
77
+ "name": "Payments",
78
+ "description": "Collect and pay stablecoin (USDC) payments with x402. Settlement is\nnon-custodial: funds move directly from payer to payee on-chain via an\nEIP-3009 authorization the payer signs with their own key, and Primitive\nnever holds funds. The payee registers a payout address and creates a\nchallenge; the payer signs and settles it under a configurable spend\npolicy (kill-switch, per-payment and per-day caps, payee allowlist).\n"
79
+ },
76
80
  {
77
81
  "name": "Webhook Deliveries",
78
82
  "description": "View and replay webhook delivery attempts"
@@ -2325,7 +2329,199 @@ const openapiDocument = {
2325
2329
  "404": { "$ref": "#/components/responses/NotFound" }
2326
2330
  }
2327
2331
  }
2328
- }
2332
+ },
2333
+ "/x402/payout-addresses": {
2334
+ "post": {
2335
+ "operationId": "registerPayoutAddress",
2336
+ "summary": "Register a payout address",
2337
+ "description": "Register (or update) the default payout address your org receives x402\npayments at, for a given network. You prove control of the address with\nan org-bound `personal_sign` signature over the message produced by the\nSDK helper `buildPayoutRegistrationMessage`. The org id is taken from your\nauthenticated key, never the body, so a captured signature can't register\nan address under another org. Exactly one default address exists per\n(org, network); registering again replaces it. A payee MUST register a\npayout address before calling `createChallenge`, because the challenge's\n`pay_to` is resolved from this directory.\n",
2338
+ "tags": ["Payments"],
2339
+ "security": [{ "BearerAuth": [] }],
2340
+ "requestBody": {
2341
+ "required": true,
2342
+ "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RegisterPayoutAddressInput" } } }
2343
+ },
2344
+ "responses": {
2345
+ "201": {
2346
+ "description": "Payout address registered (or updated) and set as default",
2347
+ "content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
2348
+ "type": "object",
2349
+ "properties": { "data": { "$ref": "#/components/schemas/X402PayoutAddress" } }
2350
+ }] } } }
2351
+ },
2352
+ "400": { "$ref": "#/components/responses/ValidationError" },
2353
+ "401": { "$ref": "#/components/responses/Unauthorized" },
2354
+ "403": { "$ref": "#/components/responses/Forbidden" },
2355
+ "422": { "$ref": "#/components/responses/UnprocessableEntity" },
2356
+ "429": { "$ref": "#/components/responses/RateLimited" }
2357
+ }
2358
+ },
2359
+ "get": {
2360
+ "operationId": "listPayoutAddresses",
2361
+ "summary": "List payout addresses",
2362
+ "description": "List your org's registered payout addresses, newest first.",
2363
+ "tags": ["Payments"],
2364
+ "security": [{ "BearerAuth": [] }],
2365
+ "responses": {
2366
+ "200": {
2367
+ "description": "Your registered payout addresses",
2368
+ "content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
2369
+ "type": "object",
2370
+ "properties": { "data": {
2371
+ "type": "array",
2372
+ "items": { "$ref": "#/components/schemas/X402PayoutAddress" }
2373
+ } }
2374
+ }] } } }
2375
+ },
2376
+ "401": { "$ref": "#/components/responses/Unauthorized" },
2377
+ "403": { "$ref": "#/components/responses/Forbidden" },
2378
+ "429": { "$ref": "#/components/responses/RateLimited" }
2379
+ }
2380
+ }
2381
+ },
2382
+ "/x402/challenges": { "post": {
2383
+ "operationId": "createChallenge",
2384
+ "summary": "Create a payment challenge",
2385
+ "description": "Create an x402 payment challenge (the payee side of a payment). The\n`pay_to` address is resolved server-side from your registered default\npayout address for the network, never from the request. The response\ncarries the `nonce_binding` and `payment_requirements` the payer needs to\nsign; hand the whole challenge object to the payer (for example in an\nemail reply). Amounts are in token base units (USDC has 6 decimals, so\n`\"10000\"` is 0.01 USDC).\n",
2386
+ "tags": ["Payments"],
2387
+ "security": [{ "BearerAuth": [] }],
2388
+ "requestBody": {
2389
+ "required": true,
2390
+ "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateChallengeInput" } } }
2391
+ },
2392
+ "responses": {
2393
+ "201": {
2394
+ "description": "Challenge created",
2395
+ "content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
2396
+ "type": "object",
2397
+ "properties": { "data": { "$ref": "#/components/schemas/X402Challenge" } }
2398
+ }] } } }
2399
+ },
2400
+ "400": { "$ref": "#/components/responses/ValidationError" },
2401
+ "401": { "$ref": "#/components/responses/Unauthorized" },
2402
+ "403": { "$ref": "#/components/responses/Forbidden" },
2403
+ "422": { "$ref": "#/components/responses/UnprocessableEntity" },
2404
+ "429": { "$ref": "#/components/responses/RateLimited" }
2405
+ }
2406
+ } },
2407
+ "/x402/challenges/{id}": { "get": {
2408
+ "operationId": "getChallenge",
2409
+ "summary": "Get a payment challenge",
2410
+ "description": "Fetch a challenge you created, to poll its `status` and settlement\nreceipt (`settle_tx`). Scoped to the challenger org that created it.\n",
2411
+ "tags": ["Payments"],
2412
+ "security": [{ "BearerAuth": [] }],
2413
+ "parameters": [{ "$ref": "#/components/parameters/ResourceId" }],
2414
+ "responses": {
2415
+ "200": {
2416
+ "description": "The challenge",
2417
+ "content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
2418
+ "type": "object",
2419
+ "properties": { "data": { "$ref": "#/components/schemas/X402Challenge" } }
2420
+ }] } } }
2421
+ },
2422
+ "400": { "$ref": "#/components/responses/ValidationError" },
2423
+ "401": { "$ref": "#/components/responses/Unauthorized" },
2424
+ "403": { "$ref": "#/components/responses/Forbidden" },
2425
+ "404": { "$ref": "#/components/responses/NotFound" },
2426
+ "429": { "$ref": "#/components/responses/RateLimited" }
2427
+ }
2428
+ } },
2429
+ "/x402/challenges/{id}/pay": { "post": {
2430
+ "operationId": "payChallenge",
2431
+ "summary": "Pay a payment challenge",
2432
+ "description": "Settle a challenge addressed to your org as payer. The request body\ncarries a signed x402 `PaymentPayload`: an EIP-3009\n`transferWithAuthorization` signed locally with your own key, whose nonce\nis bound to the challenge via the SDK's `deriveEip3009Nonce`. The platform\nverifies every signed field against its own record of the challenge,\napplies your spend policy, and settles on-chain through a facilitator.\nSettlement is non-custodial; Primitive never holds funds. Idempotent:\npaying an already-settled challenge returns the original receipt. Most\ncallers use the SDK `pay()` helper rather than building the payload by\nhand.\n",
2433
+ "tags": ["Payments"],
2434
+ "security": [{ "BearerAuth": [] }],
2435
+ "parameters": [{ "$ref": "#/components/parameters/ResourceId" }],
2436
+ "requestBody": {
2437
+ "required": true,
2438
+ "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PayChallengeInput" } } }
2439
+ },
2440
+ "responses": {
2441
+ "200": {
2442
+ "description": "Challenge settled (or already settled)",
2443
+ "content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
2444
+ "type": "object",
2445
+ "properties": { "data": { "$ref": "#/components/schemas/X402Receipt" } }
2446
+ }] } } }
2447
+ },
2448
+ "400": { "$ref": "#/components/responses/ValidationError" },
2449
+ "401": { "$ref": "#/components/responses/Unauthorized" },
2450
+ "403": { "$ref": "#/components/responses/Forbidden" },
2451
+ "404": { "$ref": "#/components/responses/NotFound" },
2452
+ "409": { "$ref": "#/components/responses/Conflict" },
2453
+ "422": { "$ref": "#/components/responses/UnprocessableEntity" },
2454
+ "429": { "$ref": "#/components/responses/RateLimited" },
2455
+ "502": { "$ref": "#/components/responses/BadGateway" }
2456
+ }
2457
+ } },
2458
+ "/x402/spend-policy": {
2459
+ "get": {
2460
+ "operationId": "getSpendPolicy",
2461
+ "summary": "Get your spend policy",
2462
+ "description": "Read your org's outbound spend policy: the kill-switch, per-payment and\nper-day caps, and the payee allowlist. Returns the defaults (no limits,\nnot paused) when no policy has been set.\n",
2463
+ "tags": ["Payments"],
2464
+ "security": [{ "BearerAuth": [] }],
2465
+ "responses": {
2466
+ "200": {
2467
+ "description": "The spend policy",
2468
+ "content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
2469
+ "type": "object",
2470
+ "properties": { "data": { "$ref": "#/components/schemas/X402SpendPolicy" } }
2471
+ }] } } }
2472
+ },
2473
+ "401": { "$ref": "#/components/responses/Unauthorized" },
2474
+ "403": { "$ref": "#/components/responses/Forbidden" },
2475
+ "429": { "$ref": "#/components/responses/RateLimited" }
2476
+ }
2477
+ },
2478
+ "put": {
2479
+ "operationId": "updateSpendPolicy",
2480
+ "summary": "Update your spend policy",
2481
+ "description": "Update your org's spend policy. Applied as a merge: only the fields you\ninclude change, and omitted fields keep their current value, so a partial\nupdate can't silently reset the kill-switch. Send an explicit `null` to\nclear a cap. Caps are in token base units.\n",
2482
+ "tags": ["Payments"],
2483
+ "security": [{ "BearerAuth": [] }],
2484
+ "requestBody": {
2485
+ "required": true,
2486
+ "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateSpendPolicyInput" } } }
2487
+ },
2488
+ "responses": {
2489
+ "200": {
2490
+ "description": "The updated spend policy",
2491
+ "content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
2492
+ "type": "object",
2493
+ "properties": { "data": { "$ref": "#/components/schemas/X402SpendPolicy" } }
2494
+ }] } } }
2495
+ },
2496
+ "400": { "$ref": "#/components/responses/ValidationError" },
2497
+ "401": { "$ref": "#/components/responses/Unauthorized" },
2498
+ "403": { "$ref": "#/components/responses/Forbidden" },
2499
+ "429": { "$ref": "#/components/responses/RateLimited" }
2500
+ }
2501
+ }
2502
+ },
2503
+ "/x402/declined-payments": { "get": {
2504
+ "operationId": "listDeclinedPayments",
2505
+ "summary": "List declined payments",
2506
+ "description": "The 50 most recent payments your org's spend policy declined, newest\nfirst. Use this to see why an outbound payment was refused (a cap, the\npayee allowlist, or the kill-switch) instead of only reading the\ndashboard.\n",
2507
+ "tags": ["Payments"],
2508
+ "security": [{ "BearerAuth": [] }],
2509
+ "responses": {
2510
+ "200": {
2511
+ "description": "Recently declined payments",
2512
+ "content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
2513
+ "type": "object",
2514
+ "properties": { "data": {
2515
+ "type": "array",
2516
+ "items": { "$ref": "#/components/schemas/X402DeclinedPayment" }
2517
+ } }
2518
+ }] } } }
2519
+ },
2520
+ "401": { "$ref": "#/components/responses/Unauthorized" },
2521
+ "403": { "$ref": "#/components/responses/Forbidden" },
2522
+ "429": { "$ref": "#/components/responses/RateLimited" }
2523
+ }
2524
+ } }
2329
2525
  },
2330
2526
  "components": {
2331
2527
  "securitySchemes": {
@@ -2492,6 +2688,32 @@ const openapiDocument = {
2492
2688
  }
2493
2689
  } }
2494
2690
  },
2691
+ "Conflict": {
2692
+ "description": "The request conflicts with the current state of the resource",
2693
+ "content": { "application/json": {
2694
+ "schema": { "$ref": "#/components/schemas/ErrorResponse" },
2695
+ "example": {
2696
+ "success": false,
2697
+ "error": {
2698
+ "code": "conflict",
2699
+ "message": "settlement already in progress"
2700
+ }
2701
+ }
2702
+ } }
2703
+ },
2704
+ "UnprocessableEntity": {
2705
+ "description": "The request was well-formed but could not be processed. For Payments\nthis covers a missing payout address, a failed payment verification, a\nspend-policy decline, or an expired challenge; `error.code` distinguishes\nthem.\n",
2706
+ "content": { "application/json": {
2707
+ "schema": { "$ref": "#/components/schemas/ErrorResponse" },
2708
+ "example": {
2709
+ "success": false,
2710
+ "error": {
2711
+ "code": "payment_declined",
2712
+ "message": "payment exceeds the per-payment cap"
2713
+ }
2714
+ }
2715
+ } }
2716
+ },
2495
2717
  "Deleted": {
2496
2718
  "description": "Resource deleted",
2497
2719
  "content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
@@ -2508,72 +2730,512 @@ const openapiDocument = {
2508
2730
  }
2509
2731
  },
2510
2732
  "schemas": {
2511
- "SuccessEnvelope": {
2733
+ "RegisterPayoutAddressInput": {
2512
2734
  "type": "object",
2513
- "properties": { "success": {
2514
- "type": "boolean",
2515
- "const": true
2516
- } },
2517
- "required": ["success", "data"]
2735
+ "additionalProperties": false,
2736
+ "properties": {
2737
+ "address": {
2738
+ "type": "string",
2739
+ "pattern": "^0x[0-9a-fA-F]{40}$",
2740
+ "description": "The payout address (your signer's own EVM address), 0x-prefixed."
2741
+ },
2742
+ "network": {
2743
+ "type": "string",
2744
+ "enum": ["base", "base-sepolia"],
2745
+ "description": "The chain the address receives on."
2746
+ },
2747
+ "signature": {
2748
+ "type": "string",
2749
+ "pattern": "^0x[0-9a-fA-F]+$",
2750
+ "description": "A `personal_sign` signature over the org-bound message produced by\nthe SDK helper `buildPayoutRegistrationMessage`. Recovered and\nchecked against `address`; the org id is bound into the signed bytes.\n"
2751
+ },
2752
+ "issued_at": {
2753
+ "type": "string",
2754
+ "format": "date-time",
2755
+ "description": "ISO-8601 timestamp embedded in the signed message. Must be within a\nshort freshness window (about 10 minutes) of server time.\n"
2756
+ },
2757
+ "label": {
2758
+ "type": "string",
2759
+ "maxLength": 80,
2760
+ "description": "Optional human-readable label."
2761
+ }
2762
+ },
2763
+ "required": [
2764
+ "address",
2765
+ "network",
2766
+ "signature",
2767
+ "issued_at"
2768
+ ]
2518
2769
  },
2519
- "ListEnvelope": {
2770
+ "X402PayoutAddress": {
2520
2771
  "type": "object",
2521
2772
  "properties": {
2522
- "success": {
2773
+ "id": {
2774
+ "type": "string",
2775
+ "format": "uuid"
2776
+ },
2777
+ "address": {
2778
+ "type": "string",
2779
+ "description": "The checksummed payout address."
2780
+ },
2781
+ "network": {
2782
+ "type": "string",
2783
+ "enum": ["base", "base-sepolia"]
2784
+ },
2785
+ "label": { "type": ["string", "null"] },
2786
+ "is_default": {
2523
2787
  "type": "boolean",
2524
- "const": true
2788
+ "description": "Exactly one address per (org, network) is the default."
2525
2789
  },
2526
- "meta": { "$ref": "#/components/schemas/PaginationMeta" }
2790
+ "verified_at": {
2791
+ "type": "string",
2792
+ "format": "date-time",
2793
+ "description": "When ownership of the address was last proven."
2794
+ },
2795
+ "created_at": {
2796
+ "type": "string",
2797
+ "format": "date-time"
2798
+ }
2527
2799
  },
2528
2800
  "required": [
2529
- "success",
2530
- "data",
2531
- "meta"
2801
+ "id",
2802
+ "address",
2803
+ "network",
2804
+ "label",
2805
+ "is_default",
2806
+ "verified_at"
2532
2807
  ]
2533
2808
  },
2534
- "PaginationMeta": {
2809
+ "CreateChallengeInput": {
2535
2810
  "type": "object",
2811
+ "additionalProperties": false,
2536
2812
  "properties": {
2537
- "total": {
2538
- "type": "integer",
2539
- "description": "Total number of matching records"
2813
+ "amount": {
2814
+ "type": "string",
2815
+ "pattern": "^[1-9][0-9]{0,38}$",
2816
+ "description": "Amount to collect, in token base units. USDC has 6 decimals, so\n`\"10000\"` is 0.01 USDC.\n"
2540
2817
  },
2541
- "limit": {
2818
+ "network": {
2819
+ "type": "string",
2820
+ "enum": ["base", "base-sepolia"]
2821
+ },
2822
+ "payer_org": {
2823
+ "type": "string",
2824
+ "format": "uuid",
2825
+ "description": "The org id allowed to pay this challenge (on-net binding). Optional.\n"
2826
+ },
2827
+ "expires_in": {
2542
2828
  "type": "integer",
2543
- "description": "Page size used for this request"
2829
+ "minimum": 60,
2830
+ "maximum": 86400,
2831
+ "description": "Seconds until the challenge expires. Defaults to 3600."
2544
2832
  },
2545
- "cursor": {
2546
- "type": ["string", "null"],
2547
- "description": "Cursor for the next page, or null if no more results"
2833
+ "resource": {
2834
+ "type": "string",
2835
+ "format": "uri",
2836
+ "maxLength": 2048,
2837
+ "description": "Optional URL identifying what is being paid for. Defaults to a\nsynthetic `x402:challenge:<id>` identifier.\n"
2838
+ },
2839
+ "description": {
2840
+ "type": "string",
2841
+ "maxLength": 512,
2842
+ "description": "Optional human-readable description of the payment."
2843
+ }
2844
+ },
2845
+ "required": ["amount", "network"]
2846
+ },
2847
+ "X402NonceBinding": {
2848
+ "type": "object",
2849
+ "description": "The interaction binding the payer hashes into the EIP-3009 nonce\n(`deriveEip3009Nonce`). Pinning the nonce to this binding is what lets an\nx402 payment ride asynchronous transports safely: a replayed challenge\ncan't redirect funds and a signed payment can't settle twice.\n",
2850
+ "properties": {
2851
+ "interaction_id": {
2852
+ "type": "string",
2853
+ "description": "Interaction id, including its `@domain` part."
2854
+ },
2855
+ "challenge_step_id": {
2856
+ "type": "string",
2857
+ "format": "uuid"
2858
+ },
2859
+ "challenge_nonce": {
2860
+ "type": "string",
2861
+ "pattern": "^[0-9a-f]{64}$",
2862
+ "description": "32 random bytes as 64 lowercase hex chars."
2548
2863
  }
2549
2864
  },
2550
2865
  "required": [
2551
- "total",
2552
- "limit",
2553
- "cursor"
2866
+ "interaction_id",
2867
+ "challenge_step_id",
2868
+ "challenge_nonce"
2554
2869
  ]
2555
2870
  },
2556
- "ErrorResponse": {
2871
+ "X402PaymentRequirements": {
2557
2872
  "type": "object",
2873
+ "description": "The x402 `PaymentRequirements` the payer signs over. Field names are\nx402's native camelCase, preserved byte-for-byte.\n",
2558
2874
  "properties": {
2559
- "success": {
2560
- "type": "boolean",
2561
- "const": false
2875
+ "scheme": {
2876
+ "type": "string",
2877
+ "description": "The x402 settlement scheme. Always `exact` for v1.",
2878
+ "example": "exact"
2562
2879
  },
2563
- "error": {
2880
+ "network": {
2881
+ "type": "string",
2882
+ "enum": ["base", "base-sepolia"]
2883
+ },
2884
+ "maxAmountRequired": {
2885
+ "type": "string",
2886
+ "description": "Amount in token base units."
2887
+ },
2888
+ "payTo": {
2889
+ "type": "string",
2890
+ "description": "The payee's resolved payout address (checksummed)."
2891
+ },
2892
+ "asset": {
2893
+ "type": "string",
2894
+ "description": "The token contract address (checksummed). USDC."
2895
+ },
2896
+ "resource": { "type": "string" },
2897
+ "description": { "type": "string" },
2898
+ "maxTimeoutSeconds": { "type": "integer" },
2899
+ "extra": {
2564
2900
  "type": "object",
2901
+ "description": "The token's load-bearing EIP-712 domain params. `name` differs by\nchain (Base mainnet USDC is `USD Coin`, Base Sepolia is `USDC`); a\nwrong value produces a signature the verifier rejects.\n",
2565
2902
  "properties": {
2566
- "code": {
2567
- "type": "string",
2568
- "enum": [
2569
- "unauthorized",
2570
- "forbidden",
2571
- "not_found",
2572
- "validation_error",
2573
- "rate_limit_exceeded",
2574
- "internal_error",
2575
- "conflict",
2576
- "mx_conflict",
2903
+ "name": { "type": "string" },
2904
+ "version": { "type": "string" }
2905
+ },
2906
+ "required": ["name", "version"]
2907
+ }
2908
+ },
2909
+ "required": [
2910
+ "scheme",
2911
+ "network",
2912
+ "maxAmountRequired",
2913
+ "payTo",
2914
+ "asset",
2915
+ "extra"
2916
+ ]
2917
+ },
2918
+ "X402Challenge": {
2919
+ "type": "object",
2920
+ "properties": {
2921
+ "id": {
2922
+ "type": "string",
2923
+ "format": "uuid"
2924
+ },
2925
+ "status": {
2926
+ "type": "string",
2927
+ "enum": [
2928
+ "pending",
2929
+ "settling",
2930
+ "settled",
2931
+ "failed",
2932
+ "expired"
2933
+ ]
2934
+ },
2935
+ "network": {
2936
+ "type": "string",
2937
+ "enum": ["base", "base-sepolia"]
2938
+ },
2939
+ "asset": {
2940
+ "type": "string",
2941
+ "description": "Token contract address (checksummed)."
2942
+ },
2943
+ "amount": {
2944
+ "type": "string",
2945
+ "description": "Amount in token base units."
2946
+ },
2947
+ "pay_to": {
2948
+ "type": "string",
2949
+ "description": "The payee's resolved payout address (checksummed)."
2950
+ },
2951
+ "payer_org": {
2952
+ "type": ["string", "null"],
2953
+ "description": "The org id bound as payer, if one was set at creation."
2954
+ },
2955
+ "resource": { "type": ["string", "null"] },
2956
+ "description": { "type": ["string", "null"] },
2957
+ "nonce_binding": { "$ref": "#/components/schemas/X402NonceBinding" },
2958
+ "settle_tx": {
2959
+ "type": ["string", "null"],
2960
+ "description": "On-chain settlement transaction hash once settled."
2961
+ },
2962
+ "settled_at": {
2963
+ "type": ["string", "null"],
2964
+ "format": "date-time"
2965
+ },
2966
+ "failure_reason": { "type": ["string", "null"] },
2967
+ "expires_at": {
2968
+ "type": "string",
2969
+ "format": "date-time"
2970
+ },
2971
+ "created_at": {
2972
+ "type": "string",
2973
+ "format": "date-time"
2974
+ },
2975
+ "payment_requirements": {
2976
+ "description": "Present on the create response. Hand the whole challenge (including\nthis) to the payer; `getChallenge` omits it (it is for status polling\nby the challenger).\n",
2977
+ "allOf": [{ "$ref": "#/components/schemas/X402PaymentRequirements" }]
2978
+ }
2979
+ },
2980
+ "required": [
2981
+ "id",
2982
+ "status",
2983
+ "network",
2984
+ "asset",
2985
+ "amount",
2986
+ "pay_to",
2987
+ "nonce_binding",
2988
+ "expires_at"
2989
+ ]
2990
+ },
2991
+ "X402PaymentPayload": {
2992
+ "type": "object",
2993
+ "description": "A signed x402 v1 `PaymentPayload`. The SDK `pay()` helper builds this;\ncallers rarely construct it by hand. Field names are x402-native.\n",
2994
+ "properties": {
2995
+ "x402Version": {
2996
+ "type": "integer",
2997
+ "const": 1
2998
+ },
2999
+ "scheme": {
3000
+ "type": "string",
3001
+ "const": "exact"
3002
+ },
3003
+ "network": {
3004
+ "type": "string",
3005
+ "enum": ["base", "base-sepolia"]
3006
+ },
3007
+ "payload": {
3008
+ "type": "object",
3009
+ "properties": {
3010
+ "signature": {
3011
+ "type": "string",
3012
+ "pattern": "^0x[0-9a-fA-F]+$",
3013
+ "description": "The EIP-712 signature over the authorization."
3014
+ },
3015
+ "authorization": {
3016
+ "type": "object",
3017
+ "description": "The EIP-3009 `transferWithAuthorization` fields, as strings.",
3018
+ "properties": {
3019
+ "from": { "type": "string" },
3020
+ "to": { "type": "string" },
3021
+ "value": { "type": "string" },
3022
+ "validAfter": { "type": "string" },
3023
+ "validBefore": { "type": "string" },
3024
+ "nonce": { "type": "string" }
3025
+ },
3026
+ "required": [
3027
+ "from",
3028
+ "to",
3029
+ "value",
3030
+ "validAfter",
3031
+ "validBefore",
3032
+ "nonce"
3033
+ ]
3034
+ }
3035
+ },
3036
+ "required": ["signature", "authorization"]
3037
+ }
3038
+ },
3039
+ "required": [
3040
+ "x402Version",
3041
+ "scheme",
3042
+ "network",
3043
+ "payload"
3044
+ ]
3045
+ },
3046
+ "PayChallengeInput": {
3047
+ "type": "object",
3048
+ "additionalProperties": false,
3049
+ "properties": { "payment": { "$ref": "#/components/schemas/X402PaymentPayload" } },
3050
+ "required": ["payment"]
3051
+ },
3052
+ "X402Receipt": {
3053
+ "type": "object",
3054
+ "properties": {
3055
+ "id": {
3056
+ "type": "string",
3057
+ "format": "uuid"
3058
+ },
3059
+ "status": {
3060
+ "type": "string",
3061
+ "enum": ["settled"]
3062
+ },
3063
+ "settle_tx": {
3064
+ "type": ["string", "null"],
3065
+ "description": "On-chain settlement transaction hash."
3066
+ }
3067
+ },
3068
+ "required": [
3069
+ "id",
3070
+ "status",
3071
+ "settle_tx"
3072
+ ]
3073
+ },
3074
+ "X402SpendPolicy": {
3075
+ "type": "object",
3076
+ "description": "The payer's outbound spend policy. Returned with defaults (not paused,\nno caps, any on-net payee) when none is set.\n",
3077
+ "properties": {
3078
+ "paused": {
3079
+ "type": "boolean",
3080
+ "description": "Kill-switch. When true, all outbound payments are refused."
3081
+ },
3082
+ "max_per_payment": {
3083
+ "type": ["string", "null"],
3084
+ "description": "Per-payment cap in token base units, or null for no cap."
3085
+ },
3086
+ "max_per_day": {
3087
+ "type": ["string", "null"],
3088
+ "description": "Rolling-day cap in token base units, or null for no cap."
3089
+ },
3090
+ "allowlist": {
3091
+ "type": ["array", "null"],
3092
+ "items": {
3093
+ "type": "string",
3094
+ "format": "uuid"
3095
+ },
3096
+ "description": "Allowed payee org ids. `null` allows any on-net payee; `[]` denies\nall.\n"
3097
+ }
3098
+ },
3099
+ "required": [
3100
+ "paused",
3101
+ "max_per_payment",
3102
+ "max_per_day",
3103
+ "allowlist"
3104
+ ]
3105
+ },
3106
+ "UpdateSpendPolicyInput": {
3107
+ "type": "object",
3108
+ "additionalProperties": false,
3109
+ "description": "Merge update: only the fields you include change; omit a field to keep\nits current value; send `null` to clear a cap.\n",
3110
+ "properties": {
3111
+ "paused": { "type": "boolean" },
3112
+ "max_per_payment": {
3113
+ "type": ["string", "null"],
3114
+ "pattern": "^[1-9][0-9]{0,38}$"
3115
+ },
3116
+ "max_per_day": {
3117
+ "type": ["string", "null"],
3118
+ "pattern": "^[1-9][0-9]{0,38}$"
3119
+ },
3120
+ "allowlist": {
3121
+ "type": ["array", "null"],
3122
+ "maxItems": 1e3,
3123
+ "items": {
3124
+ "type": "string",
3125
+ "format": "uuid"
3126
+ }
3127
+ }
3128
+ }
3129
+ },
3130
+ "X402DeclinedPayment": {
3131
+ "type": "object",
3132
+ "description": "A payment the org's spend policy refused.",
3133
+ "properties": {
3134
+ "id": {
3135
+ "type": "string",
3136
+ "format": "uuid"
3137
+ },
3138
+ "challenge_id": {
3139
+ "type": ["string", "null"],
3140
+ "format": "uuid",
3141
+ "description": "The challenge that was declined, if still present."
3142
+ },
3143
+ "counterparty_org": {
3144
+ "type": ["string", "null"],
3145
+ "format": "uuid",
3146
+ "description": "The payee (challenger) org, when known."
3147
+ },
3148
+ "network": {
3149
+ "type": "string",
3150
+ "enum": ["base", "base-sepolia"]
3151
+ },
3152
+ "amount": {
3153
+ "type": "string",
3154
+ "description": "Amount in token base units."
3155
+ },
3156
+ "reason": {
3157
+ "type": "string",
3158
+ "description": "Why the payment was declined (cap, allowlist, paused)."
3159
+ },
3160
+ "declined_at": {
3161
+ "type": "string",
3162
+ "format": "date-time"
3163
+ }
3164
+ },
3165
+ "required": [
3166
+ "id",
3167
+ "network",
3168
+ "amount",
3169
+ "reason",
3170
+ "declined_at"
3171
+ ]
3172
+ },
3173
+ "SuccessEnvelope": {
3174
+ "type": "object",
3175
+ "properties": { "success": {
3176
+ "type": "boolean",
3177
+ "const": true
3178
+ } },
3179
+ "required": ["success", "data"]
3180
+ },
3181
+ "ListEnvelope": {
3182
+ "type": "object",
3183
+ "properties": {
3184
+ "success": {
3185
+ "type": "boolean",
3186
+ "const": true
3187
+ },
3188
+ "meta": { "$ref": "#/components/schemas/PaginationMeta" }
3189
+ },
3190
+ "required": [
3191
+ "success",
3192
+ "data",
3193
+ "meta"
3194
+ ]
3195
+ },
3196
+ "PaginationMeta": {
3197
+ "type": "object",
3198
+ "properties": {
3199
+ "total": {
3200
+ "type": "integer",
3201
+ "description": "Total number of matching records"
3202
+ },
3203
+ "limit": {
3204
+ "type": "integer",
3205
+ "description": "Page size used for this request"
3206
+ },
3207
+ "cursor": {
3208
+ "type": ["string", "null"],
3209
+ "description": "Cursor for the next page, or null if no more results"
3210
+ }
3211
+ },
3212
+ "required": [
3213
+ "total",
3214
+ "limit",
3215
+ "cursor"
3216
+ ]
3217
+ },
3218
+ "ErrorResponse": {
3219
+ "type": "object",
3220
+ "properties": {
3221
+ "success": {
3222
+ "type": "boolean",
3223
+ "const": false
3224
+ },
3225
+ "error": {
3226
+ "type": "object",
3227
+ "properties": {
3228
+ "code": {
3229
+ "type": "string",
3230
+ "enum": [
3231
+ "unauthorized",
3232
+ "forbidden",
3233
+ "not_found",
3234
+ "validation_error",
3235
+ "rate_limit_exceeded",
3236
+ "internal_error",
3237
+ "conflict",
3238
+ "mx_conflict",
2577
3239
  "outbound_disabled",
2578
3240
  "cannot_send_from_domain",
2579
3241
  "recipient_not_allowed",
@@ -2597,7 +3259,14 @@ const openapiDocument = {
2597
3259
  "email_delivery_failed",
2598
3260
  "clerk_signup_failed",
2599
3261
  "no_orgs_for_user",
2600
- "org_not_accessible"
3262
+ "org_not_accessible",
3263
+ "feature_disabled",
3264
+ "no_payout_address",
3265
+ "ownership_proof_failed",
3266
+ "payment_verification_failed",
3267
+ "payment_declined",
3268
+ "challenge_expired",
3269
+ "settlement_failed"
2601
3270
  ]
2602
3271
  },
2603
3272
  "message": { "type": "string" },
@@ -11971,6 +12640,806 @@ const operationManifest = [
11971
12640
  "tag": "Inbox",
11972
12641
  "tagCommand": "inbox"
11973
12642
  },
12643
+ {
12644
+ "binaryResponse": false,
12645
+ "bodyRequired": true,
12646
+ "command": "create-challenge",
12647
+ "description": "Create an x402 payment challenge (the payee side of a payment). The\n`pay_to` address is resolved server-side from your registered default\npayout address for the network, never from the request. The response\ncarries the `nonce_binding` and `payment_requirements` the payer needs to\nsign; hand the whole challenge object to the payer (for example in an\nemail reply). Amounts are in token base units (USDC has 6 decimals, so\n`\"10000\"` is 0.01 USDC).\n",
12648
+ "hasJsonBody": true,
12649
+ "method": "POST",
12650
+ "operationId": "createChallenge",
12651
+ "path": "/x402/challenges",
12652
+ "pathParams": [],
12653
+ "queryParams": [],
12654
+ "requestSchema": {
12655
+ "type": "object",
12656
+ "additionalProperties": false,
12657
+ "properties": {
12658
+ "amount": {
12659
+ "type": "string",
12660
+ "pattern": "^[1-9][0-9]{0,38}$",
12661
+ "description": "Amount to collect, in token base units. USDC has 6 decimals, so\n`\"10000\"` is 0.01 USDC.\n"
12662
+ },
12663
+ "network": {
12664
+ "type": "string",
12665
+ "enum": ["base", "base-sepolia"]
12666
+ },
12667
+ "payer_org": {
12668
+ "type": "string",
12669
+ "format": "uuid",
12670
+ "description": "The org id allowed to pay this challenge (on-net binding). Optional.\n"
12671
+ },
12672
+ "expires_in": {
12673
+ "type": "integer",
12674
+ "minimum": 60,
12675
+ "maximum": 86400,
12676
+ "description": "Seconds until the challenge expires. Defaults to 3600."
12677
+ },
12678
+ "resource": {
12679
+ "type": "string",
12680
+ "format": "uri",
12681
+ "maxLength": 2048,
12682
+ "description": "Optional URL identifying what is being paid for. Defaults to a\nsynthetic `x402:challenge:<id>` identifier.\n"
12683
+ },
12684
+ "description": {
12685
+ "type": "string",
12686
+ "maxLength": 512,
12687
+ "description": "Optional human-readable description of the payment."
12688
+ }
12689
+ },
12690
+ "required": ["amount", "network"]
12691
+ },
12692
+ "responseSchema": {
12693
+ "type": "object",
12694
+ "properties": {
12695
+ "id": {
12696
+ "type": "string",
12697
+ "format": "uuid"
12698
+ },
12699
+ "status": {
12700
+ "type": "string",
12701
+ "enum": [
12702
+ "pending",
12703
+ "settling",
12704
+ "settled",
12705
+ "failed",
12706
+ "expired"
12707
+ ]
12708
+ },
12709
+ "network": {
12710
+ "type": "string",
12711
+ "enum": ["base", "base-sepolia"]
12712
+ },
12713
+ "asset": {
12714
+ "type": "string",
12715
+ "description": "Token contract address (checksummed)."
12716
+ },
12717
+ "amount": {
12718
+ "type": "string",
12719
+ "description": "Amount in token base units."
12720
+ },
12721
+ "pay_to": {
12722
+ "type": "string",
12723
+ "description": "The payee's resolved payout address (checksummed)."
12724
+ },
12725
+ "payer_org": {
12726
+ "type": ["string", "null"],
12727
+ "description": "The org id bound as payer, if one was set at creation."
12728
+ },
12729
+ "resource": { "type": ["string", "null"] },
12730
+ "description": { "type": ["string", "null"] },
12731
+ "nonce_binding": {
12732
+ "type": "object",
12733
+ "description": "The interaction binding the payer hashes into the EIP-3009 nonce\n(`deriveEip3009Nonce`). Pinning the nonce to this binding is what lets an\nx402 payment ride asynchronous transports safely: a replayed challenge\ncan't redirect funds and a signed payment can't settle twice.\n",
12734
+ "properties": {
12735
+ "interaction_id": {
12736
+ "type": "string",
12737
+ "description": "Interaction id, including its `@domain` part."
12738
+ },
12739
+ "challenge_step_id": {
12740
+ "type": "string",
12741
+ "format": "uuid"
12742
+ },
12743
+ "challenge_nonce": {
12744
+ "type": "string",
12745
+ "pattern": "^[0-9a-f]{64}$",
12746
+ "description": "32 random bytes as 64 lowercase hex chars."
12747
+ }
12748
+ },
12749
+ "required": [
12750
+ "interaction_id",
12751
+ "challenge_step_id",
12752
+ "challenge_nonce"
12753
+ ]
12754
+ },
12755
+ "settle_tx": {
12756
+ "type": ["string", "null"],
12757
+ "description": "On-chain settlement transaction hash once settled."
12758
+ },
12759
+ "settled_at": {
12760
+ "type": ["string", "null"],
12761
+ "format": "date-time"
12762
+ },
12763
+ "failure_reason": { "type": ["string", "null"] },
12764
+ "expires_at": {
12765
+ "type": "string",
12766
+ "format": "date-time"
12767
+ },
12768
+ "created_at": {
12769
+ "type": "string",
12770
+ "format": "date-time"
12771
+ },
12772
+ "payment_requirements": {
12773
+ "description": "Present on the create response. Hand the whole challenge (including\nthis) to the payer; `getChallenge` omits it (it is for status polling\nby the challenger).\n",
12774
+ "allOf": [{
12775
+ "type": "object",
12776
+ "description": "The x402 `PaymentRequirements` the payer signs over. Field names are\nx402's native camelCase, preserved byte-for-byte.\n",
12777
+ "properties": {
12778
+ "scheme": {
12779
+ "type": "string",
12780
+ "description": "The x402 settlement scheme. Always `exact` for v1.",
12781
+ "example": "exact"
12782
+ },
12783
+ "network": {
12784
+ "type": "string",
12785
+ "enum": ["base", "base-sepolia"]
12786
+ },
12787
+ "maxAmountRequired": {
12788
+ "type": "string",
12789
+ "description": "Amount in token base units."
12790
+ },
12791
+ "payTo": {
12792
+ "type": "string",
12793
+ "description": "The payee's resolved payout address (checksummed)."
12794
+ },
12795
+ "asset": {
12796
+ "type": "string",
12797
+ "description": "The token contract address (checksummed). USDC."
12798
+ },
12799
+ "resource": { "type": "string" },
12800
+ "description": { "type": "string" },
12801
+ "maxTimeoutSeconds": { "type": "integer" },
12802
+ "extra": {
12803
+ "type": "object",
12804
+ "description": "The token's load-bearing EIP-712 domain params. `name` differs by\nchain (Base mainnet USDC is `USD Coin`, Base Sepolia is `USDC`); a\nwrong value produces a signature the verifier rejects.\n",
12805
+ "properties": {
12806
+ "name": { "type": "string" },
12807
+ "version": { "type": "string" }
12808
+ },
12809
+ "required": ["name", "version"]
12810
+ }
12811
+ },
12812
+ "required": [
12813
+ "scheme",
12814
+ "network",
12815
+ "maxAmountRequired",
12816
+ "payTo",
12817
+ "asset",
12818
+ "extra"
12819
+ ]
12820
+ }]
12821
+ }
12822
+ },
12823
+ "required": [
12824
+ "id",
12825
+ "status",
12826
+ "network",
12827
+ "asset",
12828
+ "amount",
12829
+ "pay_to",
12830
+ "nonce_binding",
12831
+ "expires_at"
12832
+ ]
12833
+ },
12834
+ "sdkName": "createChallenge",
12835
+ "summary": "Create a payment challenge",
12836
+ "tag": "Payments",
12837
+ "tagCommand": "payments"
12838
+ },
12839
+ {
12840
+ "binaryResponse": false,
12841
+ "bodyRequired": false,
12842
+ "command": "get-challenge",
12843
+ "description": "Fetch a challenge you created, to poll its `status` and settlement\nreceipt (`settle_tx`). Scoped to the challenger org that created it.\n",
12844
+ "hasJsonBody": false,
12845
+ "method": "GET",
12846
+ "operationId": "getChallenge",
12847
+ "path": "/x402/challenges/{id}",
12848
+ "pathParams": [{
12849
+ "description": "Resource UUID",
12850
+ "enum": null,
12851
+ "name": "id",
12852
+ "required": true,
12853
+ "type": "string"
12854
+ }],
12855
+ "queryParams": [],
12856
+ "requestSchema": null,
12857
+ "responseSchema": {
12858
+ "type": "object",
12859
+ "properties": {
12860
+ "id": {
12861
+ "type": "string",
12862
+ "format": "uuid"
12863
+ },
12864
+ "status": {
12865
+ "type": "string",
12866
+ "enum": [
12867
+ "pending",
12868
+ "settling",
12869
+ "settled",
12870
+ "failed",
12871
+ "expired"
12872
+ ]
12873
+ },
12874
+ "network": {
12875
+ "type": "string",
12876
+ "enum": ["base", "base-sepolia"]
12877
+ },
12878
+ "asset": {
12879
+ "type": "string",
12880
+ "description": "Token contract address (checksummed)."
12881
+ },
12882
+ "amount": {
12883
+ "type": "string",
12884
+ "description": "Amount in token base units."
12885
+ },
12886
+ "pay_to": {
12887
+ "type": "string",
12888
+ "description": "The payee's resolved payout address (checksummed)."
12889
+ },
12890
+ "payer_org": {
12891
+ "type": ["string", "null"],
12892
+ "description": "The org id bound as payer, if one was set at creation."
12893
+ },
12894
+ "resource": { "type": ["string", "null"] },
12895
+ "description": { "type": ["string", "null"] },
12896
+ "nonce_binding": {
12897
+ "type": "object",
12898
+ "description": "The interaction binding the payer hashes into the EIP-3009 nonce\n(`deriveEip3009Nonce`). Pinning the nonce to this binding is what lets an\nx402 payment ride asynchronous transports safely: a replayed challenge\ncan't redirect funds and a signed payment can't settle twice.\n",
12899
+ "properties": {
12900
+ "interaction_id": {
12901
+ "type": "string",
12902
+ "description": "Interaction id, including its `@domain` part."
12903
+ },
12904
+ "challenge_step_id": {
12905
+ "type": "string",
12906
+ "format": "uuid"
12907
+ },
12908
+ "challenge_nonce": {
12909
+ "type": "string",
12910
+ "pattern": "^[0-9a-f]{64}$",
12911
+ "description": "32 random bytes as 64 lowercase hex chars."
12912
+ }
12913
+ },
12914
+ "required": [
12915
+ "interaction_id",
12916
+ "challenge_step_id",
12917
+ "challenge_nonce"
12918
+ ]
12919
+ },
12920
+ "settle_tx": {
12921
+ "type": ["string", "null"],
12922
+ "description": "On-chain settlement transaction hash once settled."
12923
+ },
12924
+ "settled_at": {
12925
+ "type": ["string", "null"],
12926
+ "format": "date-time"
12927
+ },
12928
+ "failure_reason": { "type": ["string", "null"] },
12929
+ "expires_at": {
12930
+ "type": "string",
12931
+ "format": "date-time"
12932
+ },
12933
+ "created_at": {
12934
+ "type": "string",
12935
+ "format": "date-time"
12936
+ },
12937
+ "payment_requirements": {
12938
+ "description": "Present on the create response. Hand the whole challenge (including\nthis) to the payer; `getChallenge` omits it (it is for status polling\nby the challenger).\n",
12939
+ "allOf": [{
12940
+ "type": "object",
12941
+ "description": "The x402 `PaymentRequirements` the payer signs over. Field names are\nx402's native camelCase, preserved byte-for-byte.\n",
12942
+ "properties": {
12943
+ "scheme": {
12944
+ "type": "string",
12945
+ "description": "The x402 settlement scheme. Always `exact` for v1.",
12946
+ "example": "exact"
12947
+ },
12948
+ "network": {
12949
+ "type": "string",
12950
+ "enum": ["base", "base-sepolia"]
12951
+ },
12952
+ "maxAmountRequired": {
12953
+ "type": "string",
12954
+ "description": "Amount in token base units."
12955
+ },
12956
+ "payTo": {
12957
+ "type": "string",
12958
+ "description": "The payee's resolved payout address (checksummed)."
12959
+ },
12960
+ "asset": {
12961
+ "type": "string",
12962
+ "description": "The token contract address (checksummed). USDC."
12963
+ },
12964
+ "resource": { "type": "string" },
12965
+ "description": { "type": "string" },
12966
+ "maxTimeoutSeconds": { "type": "integer" },
12967
+ "extra": {
12968
+ "type": "object",
12969
+ "description": "The token's load-bearing EIP-712 domain params. `name` differs by\nchain (Base mainnet USDC is `USD Coin`, Base Sepolia is `USDC`); a\nwrong value produces a signature the verifier rejects.\n",
12970
+ "properties": {
12971
+ "name": { "type": "string" },
12972
+ "version": { "type": "string" }
12973
+ },
12974
+ "required": ["name", "version"]
12975
+ }
12976
+ },
12977
+ "required": [
12978
+ "scheme",
12979
+ "network",
12980
+ "maxAmountRequired",
12981
+ "payTo",
12982
+ "asset",
12983
+ "extra"
12984
+ ]
12985
+ }]
12986
+ }
12987
+ },
12988
+ "required": [
12989
+ "id",
12990
+ "status",
12991
+ "network",
12992
+ "asset",
12993
+ "amount",
12994
+ "pay_to",
12995
+ "nonce_binding",
12996
+ "expires_at"
12997
+ ]
12998
+ },
12999
+ "sdkName": "getChallenge",
13000
+ "summary": "Get a payment challenge",
13001
+ "tag": "Payments",
13002
+ "tagCommand": "payments"
13003
+ },
13004
+ {
13005
+ "binaryResponse": false,
13006
+ "bodyRequired": false,
13007
+ "command": "get-spend-policy",
13008
+ "description": "Read your org's outbound spend policy: the kill-switch, per-payment and\nper-day caps, and the payee allowlist. Returns the defaults (no limits,\nnot paused) when no policy has been set.\n",
13009
+ "hasJsonBody": false,
13010
+ "method": "GET",
13011
+ "operationId": "getSpendPolicy",
13012
+ "path": "/x402/spend-policy",
13013
+ "pathParams": [],
13014
+ "queryParams": [],
13015
+ "requestSchema": null,
13016
+ "responseSchema": {
13017
+ "type": "object",
13018
+ "description": "The payer's outbound spend policy. Returned with defaults (not paused,\nno caps, any on-net payee) when none is set.\n",
13019
+ "properties": {
13020
+ "paused": {
13021
+ "type": "boolean",
13022
+ "description": "Kill-switch. When true, all outbound payments are refused."
13023
+ },
13024
+ "max_per_payment": {
13025
+ "type": ["string", "null"],
13026
+ "description": "Per-payment cap in token base units, or null for no cap."
13027
+ },
13028
+ "max_per_day": {
13029
+ "type": ["string", "null"],
13030
+ "description": "Rolling-day cap in token base units, or null for no cap."
13031
+ },
13032
+ "allowlist": {
13033
+ "type": ["array", "null"],
13034
+ "items": {
13035
+ "type": "string",
13036
+ "format": "uuid"
13037
+ },
13038
+ "description": "Allowed payee org ids. `null` allows any on-net payee; `[]` denies\nall.\n"
13039
+ }
13040
+ },
13041
+ "required": [
13042
+ "paused",
13043
+ "max_per_payment",
13044
+ "max_per_day",
13045
+ "allowlist"
13046
+ ]
13047
+ },
13048
+ "sdkName": "getSpendPolicy",
13049
+ "summary": "Get your spend policy",
13050
+ "tag": "Payments",
13051
+ "tagCommand": "payments"
13052
+ },
13053
+ {
13054
+ "binaryResponse": false,
13055
+ "bodyRequired": false,
13056
+ "command": "list-declined-payments",
13057
+ "description": "The 50 most recent payments your org's spend policy declined, newest\nfirst. Use this to see why an outbound payment was refused (a cap, the\npayee allowlist, or the kill-switch) instead of only reading the\ndashboard.\n",
13058
+ "hasJsonBody": false,
13059
+ "method": "GET",
13060
+ "operationId": "listDeclinedPayments",
13061
+ "path": "/x402/declined-payments",
13062
+ "pathParams": [],
13063
+ "queryParams": [],
13064
+ "requestSchema": null,
13065
+ "responseSchema": {
13066
+ "type": "array",
13067
+ "items": {
13068
+ "type": "object",
13069
+ "description": "A payment the org's spend policy refused.",
13070
+ "properties": {
13071
+ "id": {
13072
+ "type": "string",
13073
+ "format": "uuid"
13074
+ },
13075
+ "challenge_id": {
13076
+ "type": ["string", "null"],
13077
+ "format": "uuid",
13078
+ "description": "The challenge that was declined, if still present."
13079
+ },
13080
+ "counterparty_org": {
13081
+ "type": ["string", "null"],
13082
+ "format": "uuid",
13083
+ "description": "The payee (challenger) org, when known."
13084
+ },
13085
+ "network": {
13086
+ "type": "string",
13087
+ "enum": ["base", "base-sepolia"]
13088
+ },
13089
+ "amount": {
13090
+ "type": "string",
13091
+ "description": "Amount in token base units."
13092
+ },
13093
+ "reason": {
13094
+ "type": "string",
13095
+ "description": "Why the payment was declined (cap, allowlist, paused)."
13096
+ },
13097
+ "declined_at": {
13098
+ "type": "string",
13099
+ "format": "date-time"
13100
+ }
13101
+ },
13102
+ "required": [
13103
+ "id",
13104
+ "network",
13105
+ "amount",
13106
+ "reason",
13107
+ "declined_at"
13108
+ ]
13109
+ }
13110
+ },
13111
+ "sdkName": "listDeclinedPayments",
13112
+ "summary": "List declined payments",
13113
+ "tag": "Payments",
13114
+ "tagCommand": "payments"
13115
+ },
13116
+ {
13117
+ "binaryResponse": false,
13118
+ "bodyRequired": false,
13119
+ "command": "list-payout-addresses",
13120
+ "description": "List your org's registered payout addresses, newest first.",
13121
+ "hasJsonBody": false,
13122
+ "method": "GET",
13123
+ "operationId": "listPayoutAddresses",
13124
+ "path": "/x402/payout-addresses",
13125
+ "pathParams": [],
13126
+ "queryParams": [],
13127
+ "requestSchema": null,
13128
+ "responseSchema": {
13129
+ "type": "array",
13130
+ "items": {
13131
+ "type": "object",
13132
+ "properties": {
13133
+ "id": {
13134
+ "type": "string",
13135
+ "format": "uuid"
13136
+ },
13137
+ "address": {
13138
+ "type": "string",
13139
+ "description": "The checksummed payout address."
13140
+ },
13141
+ "network": {
13142
+ "type": "string",
13143
+ "enum": ["base", "base-sepolia"]
13144
+ },
13145
+ "label": { "type": ["string", "null"] },
13146
+ "is_default": {
13147
+ "type": "boolean",
13148
+ "description": "Exactly one address per (org, network) is the default."
13149
+ },
13150
+ "verified_at": {
13151
+ "type": "string",
13152
+ "format": "date-time",
13153
+ "description": "When ownership of the address was last proven."
13154
+ },
13155
+ "created_at": {
13156
+ "type": "string",
13157
+ "format": "date-time"
13158
+ }
13159
+ },
13160
+ "required": [
13161
+ "id",
13162
+ "address",
13163
+ "network",
13164
+ "label",
13165
+ "is_default",
13166
+ "verified_at"
13167
+ ]
13168
+ }
13169
+ },
13170
+ "sdkName": "listPayoutAddresses",
13171
+ "summary": "List payout addresses",
13172
+ "tag": "Payments",
13173
+ "tagCommand": "payments"
13174
+ },
13175
+ {
13176
+ "binaryResponse": false,
13177
+ "bodyRequired": true,
13178
+ "command": "pay-challenge",
13179
+ "description": "Settle a challenge addressed to your org as payer. The request body\ncarries a signed x402 `PaymentPayload`: an EIP-3009\n`transferWithAuthorization` signed locally with your own key, whose nonce\nis bound to the challenge via the SDK's `deriveEip3009Nonce`. The platform\nverifies every signed field against its own record of the challenge,\napplies your spend policy, and settles on-chain through a facilitator.\nSettlement is non-custodial; Primitive never holds funds. Idempotent:\npaying an already-settled challenge returns the original receipt. Most\ncallers use the SDK `pay()` helper rather than building the payload by\nhand.\n",
13180
+ "hasJsonBody": true,
13181
+ "method": "POST",
13182
+ "operationId": "payChallenge",
13183
+ "path": "/x402/challenges/{id}/pay",
13184
+ "pathParams": [{
13185
+ "description": "Resource UUID",
13186
+ "enum": null,
13187
+ "name": "id",
13188
+ "required": true,
13189
+ "type": "string"
13190
+ }],
13191
+ "queryParams": [],
13192
+ "requestSchema": {
13193
+ "type": "object",
13194
+ "additionalProperties": false,
13195
+ "properties": { "payment": {
13196
+ "type": "object",
13197
+ "description": "A signed x402 v1 `PaymentPayload`. The SDK `pay()` helper builds this;\ncallers rarely construct it by hand. Field names are x402-native.\n",
13198
+ "properties": {
13199
+ "x402Version": {
13200
+ "type": "integer",
13201
+ "const": 1
13202
+ },
13203
+ "scheme": {
13204
+ "type": "string",
13205
+ "const": "exact"
13206
+ },
13207
+ "network": {
13208
+ "type": "string",
13209
+ "enum": ["base", "base-sepolia"]
13210
+ },
13211
+ "payload": {
13212
+ "type": "object",
13213
+ "properties": {
13214
+ "signature": {
13215
+ "type": "string",
13216
+ "pattern": "^0x[0-9a-fA-F]+$",
13217
+ "description": "The EIP-712 signature over the authorization."
13218
+ },
13219
+ "authorization": {
13220
+ "type": "object",
13221
+ "description": "The EIP-3009 `transferWithAuthorization` fields, as strings.",
13222
+ "properties": {
13223
+ "from": { "type": "string" },
13224
+ "to": { "type": "string" },
13225
+ "value": { "type": "string" },
13226
+ "validAfter": { "type": "string" },
13227
+ "validBefore": { "type": "string" },
13228
+ "nonce": { "type": "string" }
13229
+ },
13230
+ "required": [
13231
+ "from",
13232
+ "to",
13233
+ "value",
13234
+ "validAfter",
13235
+ "validBefore",
13236
+ "nonce"
13237
+ ]
13238
+ }
13239
+ },
13240
+ "required": ["signature", "authorization"]
13241
+ }
13242
+ },
13243
+ "required": [
13244
+ "x402Version",
13245
+ "scheme",
13246
+ "network",
13247
+ "payload"
13248
+ ]
13249
+ } },
13250
+ "required": ["payment"]
13251
+ },
13252
+ "responseSchema": {
13253
+ "type": "object",
13254
+ "properties": {
13255
+ "id": {
13256
+ "type": "string",
13257
+ "format": "uuid"
13258
+ },
13259
+ "status": {
13260
+ "type": "string",
13261
+ "enum": ["settled"]
13262
+ },
13263
+ "settle_tx": {
13264
+ "type": ["string", "null"],
13265
+ "description": "On-chain settlement transaction hash."
13266
+ }
13267
+ },
13268
+ "required": [
13269
+ "id",
13270
+ "status",
13271
+ "settle_tx"
13272
+ ]
13273
+ },
13274
+ "sdkName": "payChallenge",
13275
+ "summary": "Pay a payment challenge",
13276
+ "tag": "Payments",
13277
+ "tagCommand": "payments"
13278
+ },
13279
+ {
13280
+ "binaryResponse": false,
13281
+ "bodyRequired": true,
13282
+ "command": "register-payout-address",
13283
+ "description": "Register (or update) the default payout address your org receives x402\npayments at, for a given network. You prove control of the address with\nan org-bound `personal_sign` signature over the message produced by the\nSDK helper `buildPayoutRegistrationMessage`. The org id is taken from your\nauthenticated key, never the body, so a captured signature can't register\nan address under another org. Exactly one default address exists per\n(org, network); registering again replaces it. A payee MUST register a\npayout address before calling `createChallenge`, because the challenge's\n`pay_to` is resolved from this directory.\n",
13284
+ "hasJsonBody": true,
13285
+ "method": "POST",
13286
+ "operationId": "registerPayoutAddress",
13287
+ "path": "/x402/payout-addresses",
13288
+ "pathParams": [],
13289
+ "queryParams": [],
13290
+ "requestSchema": {
13291
+ "type": "object",
13292
+ "additionalProperties": false,
13293
+ "properties": {
13294
+ "address": {
13295
+ "type": "string",
13296
+ "pattern": "^0x[0-9a-fA-F]{40}$",
13297
+ "description": "The payout address (your signer's own EVM address), 0x-prefixed."
13298
+ },
13299
+ "network": {
13300
+ "type": "string",
13301
+ "enum": ["base", "base-sepolia"],
13302
+ "description": "The chain the address receives on."
13303
+ },
13304
+ "signature": {
13305
+ "type": "string",
13306
+ "pattern": "^0x[0-9a-fA-F]+$",
13307
+ "description": "A `personal_sign` signature over the org-bound message produced by\nthe SDK helper `buildPayoutRegistrationMessage`. Recovered and\nchecked against `address`; the org id is bound into the signed bytes.\n"
13308
+ },
13309
+ "issued_at": {
13310
+ "type": "string",
13311
+ "format": "date-time",
13312
+ "description": "ISO-8601 timestamp embedded in the signed message. Must be within a\nshort freshness window (about 10 minutes) of server time.\n"
13313
+ },
13314
+ "label": {
13315
+ "type": "string",
13316
+ "maxLength": 80,
13317
+ "description": "Optional human-readable label."
13318
+ }
13319
+ },
13320
+ "required": [
13321
+ "address",
13322
+ "network",
13323
+ "signature",
13324
+ "issued_at"
13325
+ ]
13326
+ },
13327
+ "responseSchema": {
13328
+ "type": "object",
13329
+ "properties": {
13330
+ "id": {
13331
+ "type": "string",
13332
+ "format": "uuid"
13333
+ },
13334
+ "address": {
13335
+ "type": "string",
13336
+ "description": "The checksummed payout address."
13337
+ },
13338
+ "network": {
13339
+ "type": "string",
13340
+ "enum": ["base", "base-sepolia"]
13341
+ },
13342
+ "label": { "type": ["string", "null"] },
13343
+ "is_default": {
13344
+ "type": "boolean",
13345
+ "description": "Exactly one address per (org, network) is the default."
13346
+ },
13347
+ "verified_at": {
13348
+ "type": "string",
13349
+ "format": "date-time",
13350
+ "description": "When ownership of the address was last proven."
13351
+ },
13352
+ "created_at": {
13353
+ "type": "string",
13354
+ "format": "date-time"
13355
+ }
13356
+ },
13357
+ "required": [
13358
+ "id",
13359
+ "address",
13360
+ "network",
13361
+ "label",
13362
+ "is_default",
13363
+ "verified_at"
13364
+ ]
13365
+ },
13366
+ "sdkName": "registerPayoutAddress",
13367
+ "summary": "Register a payout address",
13368
+ "tag": "Payments",
13369
+ "tagCommand": "payments"
13370
+ },
13371
+ {
13372
+ "binaryResponse": false,
13373
+ "bodyRequired": true,
13374
+ "command": "update-spend-policy",
13375
+ "description": "Update your org's spend policy. Applied as a merge: only the fields you\ninclude change, and omitted fields keep their current value, so a partial\nupdate can't silently reset the kill-switch. Send an explicit `null` to\nclear a cap. Caps are in token base units.\n",
13376
+ "hasJsonBody": true,
13377
+ "method": "PUT",
13378
+ "operationId": "updateSpendPolicy",
13379
+ "path": "/x402/spend-policy",
13380
+ "pathParams": [],
13381
+ "queryParams": [],
13382
+ "requestSchema": {
13383
+ "type": "object",
13384
+ "additionalProperties": false,
13385
+ "description": "Merge update: only the fields you include change; omit a field to keep\nits current value; send `null` to clear a cap.\n",
13386
+ "properties": {
13387
+ "paused": { "type": "boolean" },
13388
+ "max_per_payment": {
13389
+ "type": ["string", "null"],
13390
+ "pattern": "^[1-9][0-9]{0,38}$"
13391
+ },
13392
+ "max_per_day": {
13393
+ "type": ["string", "null"],
13394
+ "pattern": "^[1-9][0-9]{0,38}$"
13395
+ },
13396
+ "allowlist": {
13397
+ "type": ["array", "null"],
13398
+ "maxItems": 1e3,
13399
+ "items": {
13400
+ "type": "string",
13401
+ "format": "uuid"
13402
+ }
13403
+ }
13404
+ }
13405
+ },
13406
+ "responseSchema": {
13407
+ "type": "object",
13408
+ "description": "The payer's outbound spend policy. Returned with defaults (not paused,\nno caps, any on-net payee) when none is set.\n",
13409
+ "properties": {
13410
+ "paused": {
13411
+ "type": "boolean",
13412
+ "description": "Kill-switch. When true, all outbound payments are refused."
13413
+ },
13414
+ "max_per_payment": {
13415
+ "type": ["string", "null"],
13416
+ "description": "Per-payment cap in token base units, or null for no cap."
13417
+ },
13418
+ "max_per_day": {
13419
+ "type": ["string", "null"],
13420
+ "description": "Rolling-day cap in token base units, or null for no cap."
13421
+ },
13422
+ "allowlist": {
13423
+ "type": ["array", "null"],
13424
+ "items": {
13425
+ "type": "string",
13426
+ "format": "uuid"
13427
+ },
13428
+ "description": "Allowed payee org ids. `null` allows any on-net payee; `[]` denies\nall.\n"
13429
+ }
13430
+ },
13431
+ "required": [
13432
+ "paused",
13433
+ "max_per_payment",
13434
+ "max_per_day",
13435
+ "allowlist"
13436
+ ]
13437
+ },
13438
+ "sdkName": "updateSpendPolicy",
13439
+ "summary": "Update your spend policy",
13440
+ "tag": "Payments",
13441
+ "tagCommand": "payments"
13442
+ },
11974
13443
  {
11975
13444
  "binaryResponse": false,
11976
13445
  "bodyRequired": true,