@1claw/openapi-spec 0.59.9 → 0.60.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 +21 -1
- package/openapi.json +3532 -312
- package/openapi.yaml +2193 -63
- package/package.json +1 -1
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.
|
|
5
|
+
version: "0.60.0"
|
|
6
6
|
description: |
|
|
7
7
|
Secure secret management for AI agents. Provides vaults, secrets,
|
|
8
8
|
policy-based access control, agent identity, Intents API,
|
|
@@ -836,7 +836,21 @@ paths:
|
|
|
836
836
|
post:
|
|
837
837
|
tags: [Approvals]
|
|
838
838
|
summary: Request human approval (agent-only)
|
|
839
|
-
description:
|
|
839
|
+
description: |
|
|
840
|
+
Ask a human to approve an action.
|
|
841
|
+
|
|
842
|
+
Two families of action are accepted:
|
|
843
|
+
|
|
844
|
+
* the control-plane requests `access_request`, `policy_request`
|
|
845
|
+
and `binding_request`, which widen the agent's own authority; and
|
|
846
|
+
* business actions named `namespace.verb` (`refund.create`,
|
|
847
|
+
`social.post`), whose meaning is carried by `summary` and `payload`.
|
|
848
|
+
|
|
849
|
+
Actions that 1Claw itself executes on approval — `policy_change`,
|
|
850
|
+
`card_order`, `agent_transaction`, `agent_execution`,
|
|
851
|
+
`agent_sign_intent` — are created by the platform and rejected here,
|
|
852
|
+
because the summary a human reads would be agent-supplied while the
|
|
853
|
+
side effect would not be.
|
|
840
854
|
operationId: requestApproval
|
|
841
855
|
requestBody:
|
|
842
856
|
required: true
|
|
@@ -848,20 +862,42 @@ paths:
|
|
|
848
862
|
properties:
|
|
849
863
|
action:
|
|
850
864
|
type: string
|
|
851
|
-
|
|
865
|
+
maxLength: 64
|
|
866
|
+
description: "Control-plane action, or a business action named `namespace.verb`."
|
|
867
|
+
example: refund.create
|
|
852
868
|
target_type:
|
|
853
869
|
type: string
|
|
854
870
|
target_id:
|
|
855
871
|
type: string
|
|
856
872
|
summary:
|
|
857
873
|
type: object
|
|
858
|
-
description: "
|
|
874
|
+
description: "What the human is shown: title, body, and key-value fields."
|
|
875
|
+
example: {title: "Refund $49.99", body: "Order #1234 arrived damaged."}
|
|
876
|
+
payload:
|
|
877
|
+
type: object
|
|
878
|
+
description: |
|
|
879
|
+
What the action will actually do. The enforced risk tier and
|
|
880
|
+
the human-readable line are derived from this, not from
|
|
881
|
+
`summary` — the two can disagree, and only this one describes
|
|
882
|
+
what happens if the human approves.
|
|
883
|
+
example: {amount_usd: "49.99", customer_email: "a.user@example.com"}
|
|
859
884
|
reason:
|
|
860
885
|
type: string
|
|
886
|
+
declared_risk_tier:
|
|
887
|
+
type: integer
|
|
888
|
+
minimum: 1
|
|
889
|
+
maximum: 3
|
|
890
|
+
description: |
|
|
891
|
+
Advisory. The server derives the enforced tier from the agent's
|
|
892
|
+
`action_approval_policy` and the payload, then takes the higher
|
|
893
|
+
of the two: a caller may raise its own bar, never lower it.
|
|
894
|
+
The response returns both.
|
|
861
895
|
risk_tier:
|
|
862
896
|
type: integer
|
|
863
897
|
minimum: 1
|
|
864
|
-
maximum:
|
|
898
|
+
maximum: 3
|
|
899
|
+
deprecated: true
|
|
900
|
+
description: "Former name for `declared_risk_tier`. Still accepted."
|
|
865
901
|
responses:
|
|
866
902
|
"202":
|
|
867
903
|
description: Approval request created
|
|
@@ -1649,7 +1685,17 @@ paths:
|
|
|
1649
1685
|
schema:
|
|
1650
1686
|
$ref: "#/components/schemas/VaultResponse"
|
|
1651
1687
|
"400":
|
|
1652
|
-
|
|
1688
|
+
description: The name is empty or longer than 255 characters. Checked before the consensus gate and the quota, so a malformed request consumes neither an approval nor a rate-limit slot.
|
|
1689
|
+
content:
|
|
1690
|
+
application/json:
|
|
1691
|
+
schema:
|
|
1692
|
+
$ref: "#/components/schemas/ProblemDetails"
|
|
1693
|
+
"409":
|
|
1694
|
+
description: A vault with that name already exists in this organization. Names are unique per org; this previously surfaced as a 500.
|
|
1695
|
+
content:
|
|
1696
|
+
application/json:
|
|
1697
|
+
schema:
|
|
1698
|
+
$ref: "#/components/schemas/ProblemDetails"
|
|
1653
1699
|
get:
|
|
1654
1700
|
tags: [Vaults]
|
|
1655
1701
|
summary: List vaults
|
|
@@ -6652,6 +6698,224 @@ paths:
|
|
|
6652
6698
|
"404":
|
|
6653
6699
|
$ref: "#/components/responses/NotFound"
|
|
6654
6700
|
|
|
6701
|
+
/v1/platform/apps/{appId}/fleets/{template_id}:
|
|
6702
|
+
get:
|
|
6703
|
+
tags: [Platform]
|
|
6704
|
+
summary: Fleet summary for a template
|
|
6705
|
+
description: >
|
|
6706
|
+
Every agent this template provisioned, as one cohort: how many there are, how
|
|
6707
|
+
they split across the template versions they were built from, and how many a
|
|
6708
|
+
previous rollout declined to touch. plt_ or user JWT.
|
|
6709
|
+
operationId: getFleet
|
|
6710
|
+
security:
|
|
6711
|
+
- BearerAuth: []
|
|
6712
|
+
parameters:
|
|
6713
|
+
- in: path
|
|
6714
|
+
name: appId
|
|
6715
|
+
required: true
|
|
6716
|
+
schema:
|
|
6717
|
+
type: string
|
|
6718
|
+
format: uuid
|
|
6719
|
+
- in: path
|
|
6720
|
+
name: template_id
|
|
6721
|
+
required: true
|
|
6722
|
+
schema:
|
|
6723
|
+
type: string
|
|
6724
|
+
format: uuid
|
|
6725
|
+
responses:
|
|
6726
|
+
"200":
|
|
6727
|
+
description: Fleet summary
|
|
6728
|
+
content:
|
|
6729
|
+
application/json:
|
|
6730
|
+
schema:
|
|
6731
|
+
$ref: "#/components/schemas/FleetSummaryResponse"
|
|
6732
|
+
"404":
|
|
6733
|
+
$ref: "#/components/responses/NotFound"
|
|
6734
|
+
/v1/platform/apps/{appId}/fleets/{template_id}/agents:
|
|
6735
|
+
get:
|
|
6736
|
+
tags: [Platform]
|
|
6737
|
+
summary: List the agents in a fleet
|
|
6738
|
+
operationId: listFleetAgents
|
|
6739
|
+
security:
|
|
6740
|
+
- BearerAuth: []
|
|
6741
|
+
parameters:
|
|
6742
|
+
- in: path
|
|
6743
|
+
name: appId
|
|
6744
|
+
required: true
|
|
6745
|
+
schema:
|
|
6746
|
+
type: string
|
|
6747
|
+
format: uuid
|
|
6748
|
+
- in: path
|
|
6749
|
+
name: template_id
|
|
6750
|
+
required: true
|
|
6751
|
+
schema:
|
|
6752
|
+
type: string
|
|
6753
|
+
format: uuid
|
|
6754
|
+
- in: query
|
|
6755
|
+
name: limit
|
|
6756
|
+
schema:
|
|
6757
|
+
type: integer
|
|
6758
|
+
default: 50
|
|
6759
|
+
minimum: 1
|
|
6760
|
+
maximum: 500
|
|
6761
|
+
- in: query
|
|
6762
|
+
name: offset
|
|
6763
|
+
schema:
|
|
6764
|
+
type: integer
|
|
6765
|
+
default: 0
|
|
6766
|
+
minimum: 0
|
|
6767
|
+
responses:
|
|
6768
|
+
"200":
|
|
6769
|
+
description: Agents in the fleet
|
|
6770
|
+
content:
|
|
6771
|
+
application/json:
|
|
6772
|
+
schema:
|
|
6773
|
+
$ref: "#/components/schemas/ListFleetAgentsResponse"
|
|
6774
|
+
"404":
|
|
6775
|
+
$ref: "#/components/responses/NotFound"
|
|
6776
|
+
/v1/platform/apps/{appId}/fleets/{template_id}/bulk-patch:
|
|
6777
|
+
post:
|
|
6778
|
+
tags: [Platform]
|
|
6779
|
+
summary: Patch every agent in a fleet
|
|
6780
|
+
description: >
|
|
6781
|
+
Applies one patch to every agent in the cohort. The field allowlist is
|
|
6782
|
+
deliberately narrower than a single-agent PATCH: guardrails and capability
|
|
6783
|
+
flags (intents_api_enabled, execution_intents_enabled) cannot be changed here,
|
|
6784
|
+
because at cohort scale nobody reviews the change per agent. Read the
|
|
6785
|
+
allowlist from bulk_patchable_fields on the fleet summary rather than hard-coding
|
|
6786
|
+
it. A field outside it returns 400 naming the field.
|
|
6787
|
+
operationId: bulkPatchFleet
|
|
6788
|
+
security:
|
|
6789
|
+
- BearerAuth: []
|
|
6790
|
+
parameters:
|
|
6791
|
+
- in: path
|
|
6792
|
+
name: appId
|
|
6793
|
+
required: true
|
|
6794
|
+
schema:
|
|
6795
|
+
type: string
|
|
6796
|
+
format: uuid
|
|
6797
|
+
- in: path
|
|
6798
|
+
name: template_id
|
|
6799
|
+
required: true
|
|
6800
|
+
schema:
|
|
6801
|
+
type: string
|
|
6802
|
+
format: uuid
|
|
6803
|
+
requestBody:
|
|
6804
|
+
required: true
|
|
6805
|
+
content:
|
|
6806
|
+
application/json:
|
|
6807
|
+
schema:
|
|
6808
|
+
type: object
|
|
6809
|
+
required: [patch]
|
|
6810
|
+
properties:
|
|
6811
|
+
patch:
|
|
6812
|
+
type: object
|
|
6813
|
+
additionalProperties: true
|
|
6814
|
+
description: Fields to set on every agent in the cohort.
|
|
6815
|
+
responses:
|
|
6816
|
+
"200":
|
|
6817
|
+
description: Patch applied
|
|
6818
|
+
content:
|
|
6819
|
+
application/json:
|
|
6820
|
+
schema:
|
|
6821
|
+
type: object
|
|
6822
|
+
properties:
|
|
6823
|
+
fields_applied:
|
|
6824
|
+
type: array
|
|
6825
|
+
items: { type: string }
|
|
6826
|
+
agents_matched: { type: integer, format: int64 }
|
|
6827
|
+
agents_updated: { type: integer, format: int64 }
|
|
6828
|
+
"400":
|
|
6829
|
+
description: A field outside the bulk-patch allowlist, or an empty patch
|
|
6830
|
+
"404":
|
|
6831
|
+
$ref: "#/components/responses/NotFound"
|
|
6832
|
+
/v1/platform/apps/{appId}/fleets/{template_id}/rollout:
|
|
6833
|
+
post:
|
|
6834
|
+
tags: [Platform]
|
|
6835
|
+
summary: Roll the current template version out to its fleet
|
|
6836
|
+
description: >
|
|
6837
|
+
Brings every agent in the cohort up to the template's current version. An agent
|
|
6838
|
+
changed outside fleet control is skipped rather than corrected, and the fields
|
|
6839
|
+
that caused the skip are recorded on it. force=true overrides that skip but
|
|
6840
|
+
still cannot carry a guardrail or a capability flag. dry_run=true reports what
|
|
6841
|
+
would happen and claims nothing, so it never blocks a real rollout. Only one
|
|
6842
|
+
rollout may run per template at a time; a second returns 409.
|
|
6843
|
+
operationId: rolloutFleet
|
|
6844
|
+
security:
|
|
6845
|
+
- BearerAuth: []
|
|
6846
|
+
parameters:
|
|
6847
|
+
- in: path
|
|
6848
|
+
name: appId
|
|
6849
|
+
required: true
|
|
6850
|
+
schema:
|
|
6851
|
+
type: string
|
|
6852
|
+
format: uuid
|
|
6853
|
+
- in: path
|
|
6854
|
+
name: template_id
|
|
6855
|
+
required: true
|
|
6856
|
+
schema:
|
|
6857
|
+
type: string
|
|
6858
|
+
format: uuid
|
|
6859
|
+
requestBody:
|
|
6860
|
+
required: false
|
|
6861
|
+
content:
|
|
6862
|
+
application/json:
|
|
6863
|
+
schema:
|
|
6864
|
+
type: object
|
|
6865
|
+
properties:
|
|
6866
|
+
force:
|
|
6867
|
+
type: boolean
|
|
6868
|
+
default: false
|
|
6869
|
+
description: Overwrite hand edits. Cannot carry guardrails.
|
|
6870
|
+
dry_run:
|
|
6871
|
+
type: boolean
|
|
6872
|
+
default: false
|
|
6873
|
+
description: Report the plan without applying it.
|
|
6874
|
+
responses:
|
|
6875
|
+
"200":
|
|
6876
|
+
description: Rollout result
|
|
6877
|
+
content:
|
|
6878
|
+
application/json:
|
|
6879
|
+
schema:
|
|
6880
|
+
$ref: "#/components/schemas/FleetRolloutResponse"
|
|
6881
|
+
"409":
|
|
6882
|
+
description: A rollout is already running for this template
|
|
6883
|
+
"404":
|
|
6884
|
+
$ref: "#/components/responses/NotFound"
|
|
6885
|
+
/v1/platform/apps/{appId}/fleets/{template_id}/pause:
|
|
6886
|
+
post:
|
|
6887
|
+
tags: [Platform]
|
|
6888
|
+
summary: Deactivate every agent in a fleet
|
|
6889
|
+
description: >
|
|
6890
|
+
Sets is_active=false on the whole cohort. The blast radius is the point: this
|
|
6891
|
+
exists for the moment an operator needs a thousand agents to stop at once.
|
|
6892
|
+
operationId: pauseFleet
|
|
6893
|
+
security:
|
|
6894
|
+
- BearerAuth: []
|
|
6895
|
+
parameters:
|
|
6896
|
+
- in: path
|
|
6897
|
+
name: appId
|
|
6898
|
+
required: true
|
|
6899
|
+
schema:
|
|
6900
|
+
type: string
|
|
6901
|
+
format: uuid
|
|
6902
|
+
- in: path
|
|
6903
|
+
name: template_id
|
|
6904
|
+
required: true
|
|
6905
|
+
schema:
|
|
6906
|
+
type: string
|
|
6907
|
+
format: uuid
|
|
6908
|
+
responses:
|
|
6909
|
+
"200":
|
|
6910
|
+
description: Agents paused
|
|
6911
|
+
content:
|
|
6912
|
+
application/json:
|
|
6913
|
+
schema:
|
|
6914
|
+
type: object
|
|
6915
|
+
properties:
|
|
6916
|
+
agents_paused: { type: integer, format: int64 }
|
|
6917
|
+
"404":
|
|
6918
|
+
$ref: "#/components/responses/NotFound"
|
|
6655
6919
|
/v1/platform/apps/{appId}/templates/{template_id}/preview:
|
|
6656
6920
|
post:
|
|
6657
6921
|
tags: [Platform]
|
|
@@ -7504,6 +7768,26 @@ paths:
|
|
|
7504
7768
|
"404":
|
|
7505
7769
|
$ref: "#/components/responses/NotFound"
|
|
7506
7770
|
|
|
7771
|
+
post:
|
|
7772
|
+
tags: [Platform]
|
|
7773
|
+
summary: Create an approval on a platform connection
|
|
7774
|
+
operationId: createConnectionApproval
|
|
7775
|
+
security:
|
|
7776
|
+
- BearerAuth: []
|
|
7777
|
+
parameters:
|
|
7778
|
+
- in: path
|
|
7779
|
+
name: connectionId
|
|
7780
|
+
required: true
|
|
7781
|
+
schema:
|
|
7782
|
+
type: string
|
|
7783
|
+
format: uuid
|
|
7784
|
+
responses:
|
|
7785
|
+
"201":
|
|
7786
|
+
description: Approval created
|
|
7787
|
+
"403":
|
|
7788
|
+
$ref: "#/components/responses/Forbidden"
|
|
7789
|
+
"404":
|
|
7790
|
+
$ref: "#/components/responses/NotFound"
|
|
7507
7791
|
/v1/platform/connections/{connectionId}/approvals/{approvalId}:
|
|
7508
7792
|
get:
|
|
7509
7793
|
tags: [Platform]
|
|
@@ -7896,6 +8180,32 @@ paths:
|
|
|
7896
8180
|
"404":
|
|
7897
8181
|
$ref: "#/components/responses/NotFound"
|
|
7898
8182
|
|
|
8183
|
+
post:
|
|
8184
|
+
tags: [Platform]
|
|
8185
|
+
summary: "Alias for PATCH on this path — same handler, same limited settings. Present because some clients cannot send PATCH."
|
|
8186
|
+
operationId: postConnectionAgent
|
|
8187
|
+
security:
|
|
8188
|
+
- BearerAuth: []
|
|
8189
|
+
parameters:
|
|
8190
|
+
- in: path
|
|
8191
|
+
name: connectionId
|
|
8192
|
+
required: true
|
|
8193
|
+
schema:
|
|
8194
|
+
type: string
|
|
8195
|
+
format: uuid
|
|
8196
|
+
- in: path
|
|
8197
|
+
name: agentId
|
|
8198
|
+
required: true
|
|
8199
|
+
schema:
|
|
8200
|
+
type: string
|
|
8201
|
+
format: uuid
|
|
8202
|
+
responses:
|
|
8203
|
+
"200":
|
|
8204
|
+
description: Agent updated
|
|
8205
|
+
"403":
|
|
8206
|
+
$ref: "#/components/responses/Forbidden"
|
|
8207
|
+
"404":
|
|
8208
|
+
$ref: "#/components/responses/NotFound"
|
|
7899
8209
|
/v1/platform/connections/{connectionId}/portfolio:
|
|
7900
8210
|
get:
|
|
7901
8211
|
tags: [Platform]
|
|
@@ -8713,6 +9023,30 @@ paths:
|
|
|
8713
9023
|
"409":
|
|
8714
9024
|
$ref: "#/components/responses/Conflict"
|
|
8715
9025
|
|
|
9026
|
+
post:
|
|
9027
|
+
tags: [Approvals]
|
|
9028
|
+
summary: "One-click approve or deny, as an API call. The GET on this path is the preview an email link opens; this is the decision itself."
|
|
9029
|
+
operationId: quickDecide
|
|
9030
|
+
requestBody:
|
|
9031
|
+
required: true
|
|
9032
|
+
content:
|
|
9033
|
+
application/json:
|
|
9034
|
+
schema:
|
|
9035
|
+
type: object
|
|
9036
|
+
required: [token, decision]
|
|
9037
|
+
properties:
|
|
9038
|
+
token:
|
|
9039
|
+
type: string
|
|
9040
|
+
decision:
|
|
9041
|
+
type: string
|
|
9042
|
+
enum: [approve, deny]
|
|
9043
|
+
responses:
|
|
9044
|
+
"200":
|
|
9045
|
+
description: Decision recorded
|
|
9046
|
+
"400":
|
|
9047
|
+
description: Malformed or expired token
|
|
9048
|
+
"404":
|
|
9049
|
+
$ref: "#/components/responses/NotFound"
|
|
8716
9050
|
/v1/deposit-destinations:
|
|
8717
9051
|
post:
|
|
8718
9052
|
tags: [Treasury]
|
|
@@ -10516,6 +10850,17 @@ paths:
|
|
|
10516
10850
|
$ref: "#/components/responses/Forbidden"
|
|
10517
10851
|
"404":
|
|
10518
10852
|
$ref: "#/components/responses/NotFound"
|
|
10853
|
+
"503":
|
|
10854
|
+
description: |
|
|
10855
|
+
The runtime's last start failed less than 120 seconds ago and is not
|
|
10856
|
+
being retried yet. Chat starts a stopped runtime, so a client that
|
|
10857
|
+
retries on failure turns every attempt into another deploy — one
|
|
10858
|
+
polling client did exactly that every 8 seconds for days. Wait out
|
|
10859
|
+
the cooldown, or call the start endpoint to see the underlying error.
|
|
10860
|
+
content:
|
|
10861
|
+
application/json:
|
|
10862
|
+
schema:
|
|
10863
|
+
$ref: "#/components/schemas/ProblemDetails"
|
|
10519
10864
|
|
|
10520
10865
|
# ---------------------------------------------------------------------------
|
|
10521
10866
|
# Agent Memory
|
|
@@ -10563,12 +10908,10 @@ paths:
|
|
|
10563
10908
|
$ref: "#/components/responses/Unauthorized"
|
|
10564
10909
|
"404":
|
|
10565
10910
|
$ref: "#/components/responses/NotFound"
|
|
10566
|
-
|
|
10567
|
-
/v1/agents/{agent_id}/memory/{namespace}/{key}:
|
|
10568
|
-
put:
|
|
10911
|
+
delete:
|
|
10569
10912
|
tags: [Agent Memory]
|
|
10570
|
-
summary:
|
|
10571
|
-
operationId:
|
|
10913
|
+
summary: "Delete a memory namespace and every entry in it. Destructive and not reversible; there is no per-entry confirmation."
|
|
10914
|
+
operationId: deleteMemoryNamespace
|
|
10572
10915
|
parameters:
|
|
10573
10916
|
- $ref: "#/components/parameters/AgentId"
|
|
10574
10917
|
- name: namespace
|
|
@@ -10576,10 +10919,30 @@ paths:
|
|
|
10576
10919
|
required: true
|
|
10577
10920
|
schema:
|
|
10578
10921
|
type: string
|
|
10579
|
-
|
|
10580
|
-
|
|
10581
|
-
|
|
10582
|
-
|
|
10922
|
+
responses:
|
|
10923
|
+
"204":
|
|
10924
|
+
description: Namespace deleted
|
|
10925
|
+
"401":
|
|
10926
|
+
$ref: "#/components/responses/Unauthorized"
|
|
10927
|
+
"404":
|
|
10928
|
+
$ref: "#/components/responses/NotFound"
|
|
10929
|
+
|
|
10930
|
+
/v1/agents/{agent_id}/memory/{namespace}/{key}:
|
|
10931
|
+
put:
|
|
10932
|
+
tags: [Agent Memory]
|
|
10933
|
+
summary: Put memory entry
|
|
10934
|
+
operationId: putMemoryEntry
|
|
10935
|
+
parameters:
|
|
10936
|
+
- $ref: "#/components/parameters/AgentId"
|
|
10937
|
+
- name: namespace
|
|
10938
|
+
in: path
|
|
10939
|
+
required: true
|
|
10940
|
+
schema:
|
|
10941
|
+
type: string
|
|
10942
|
+
- name: key
|
|
10943
|
+
in: path
|
|
10944
|
+
required: true
|
|
10945
|
+
schema:
|
|
10583
10946
|
type: string
|
|
10584
10947
|
requestBody:
|
|
10585
10948
|
required: true
|
|
@@ -11236,49 +11599,1373 @@ paths:
|
|
|
11236
11599
|
"200":
|
|
11237
11600
|
description: Webhook processed
|
|
11238
11601
|
|
|
11239
|
-
/v1/
|
|
11602
|
+
/v1/platform/apps/{app_id}/usage:
|
|
11603
|
+
get:
|
|
11604
|
+
tags: [Platform API]
|
|
11605
|
+
summary: Usage for every connection on an app
|
|
11606
|
+
description: |
|
|
11607
|
+
Billable activity for the current month, grouped by end-user connection,
|
|
11608
|
+
**plus what could not be charged to one**.
|
|
11609
|
+
|
|
11610
|
+
The `unattributed` block is not an implementation detail. Summing only the
|
|
11611
|
+
per-connection numbers gives a figure that will not match the invoice you
|
|
11612
|
+
are reconciling against, and the gap is usage that belongs to a real
|
|
11613
|
+
end-user we cannot name.
|
|
11614
|
+
|
|
11615
|
+
Two kinds, deliberately kept apart:
|
|
11616
|
+
|
|
11617
|
+
* `none` — no platform linkage at all. Normal for most traffic, not a problem.
|
|
11618
|
+
* `ambiguous` — the agent belongs to several connections and no
|
|
11619
|
+
`X-Platform-Connection` header said which. This usage belongs to
|
|
11620
|
+
*someone*. `has_ambiguous_usage` flags it so you do not have to notice
|
|
11621
|
+
a non-zero nested number.
|
|
11622
|
+
|
|
11623
|
+
`totals` is derived from the parts, never queried separately, so it cannot
|
|
11624
|
+
disagree with its own breakdown.
|
|
11625
|
+
operationId: getAppUsage
|
|
11626
|
+
parameters:
|
|
11627
|
+
- name: app_id
|
|
11628
|
+
in: path
|
|
11629
|
+
required: true
|
|
11630
|
+
schema: { type: string, format: uuid }
|
|
11631
|
+
responses:
|
|
11632
|
+
"200":
|
|
11633
|
+
description: Usage report
|
|
11634
|
+
content:
|
|
11635
|
+
application/json:
|
|
11636
|
+
schema:
|
|
11637
|
+
$ref: "#/components/schemas/AppUsageReport"
|
|
11638
|
+
"404":
|
|
11639
|
+
$ref: "#/components/responses/NotFound"
|
|
11640
|
+
|
|
11641
|
+
/v1/platform/apps/{app_id}/usage/export:
|
|
11642
|
+
get:
|
|
11643
|
+
tags: [Platform API]
|
|
11644
|
+
summary: Usage as CSV for billing reconciliation
|
|
11645
|
+
description: |
|
|
11646
|
+
The same report as `GET /usage`, as CSV. Includes the `ambiguous`, `none`
|
|
11647
|
+
and `total` rows — a CSV listing only connections looks complete and is
|
|
11648
|
+
not, and whoever imports it has no way to tell.
|
|
11649
|
+
operationId: exportAppUsage
|
|
11650
|
+
parameters:
|
|
11651
|
+
- name: app_id
|
|
11652
|
+
in: path
|
|
11653
|
+
required: true
|
|
11654
|
+
schema: { type: string, format: uuid }
|
|
11655
|
+
responses:
|
|
11656
|
+
"200":
|
|
11657
|
+
description: CSV
|
|
11658
|
+
content:
|
|
11659
|
+
text/csv:
|
|
11660
|
+
schema: { type: string }
|
|
11661
|
+
"404":
|
|
11662
|
+
$ref: "#/components/responses/NotFound"
|
|
11663
|
+
|
|
11664
|
+
/v1/org/apply:
|
|
11240
11665
|
post:
|
|
11241
|
-
tags: [
|
|
11242
|
-
summary:
|
|
11243
|
-
description:
|
|
11244
|
-
|
|
11666
|
+
tags: [Organization]
|
|
11667
|
+
summary: Apply a chart
|
|
11668
|
+
description: |
|
|
11669
|
+
Create what the chart describes. Human users only.
|
|
11670
|
+
|
|
11671
|
+
**Apply calls the same handlers the HTTP routes call.** Creating a vault
|
|
11672
|
+
runs five gates before anything is written — the delegation scope, a name
|
|
11673
|
+
check, control-plane consensus, a creation rate limit and the tier quota
|
|
11674
|
+
— and creating an agent runs its own. A reconciler that wrote through the
|
|
11675
|
+
repositories would skip all of them and would look, in review, exactly
|
|
11676
|
+
like one that did not.
|
|
11677
|
+
|
|
11678
|
+
So if your org has consensus configured on `vault.create`, applying a
|
|
11679
|
+
chart queues an approval exactly as a dashboard click would. That resource
|
|
11680
|
+
comes back as `awaiting_approval` rather than failing the whole chart.
|
|
11681
|
+
|
|
11682
|
+
Per-resource results: `created`, `unchanged`, `skipped`, `refused`,
|
|
11683
|
+
`awaiting_approval`, `failed`. `needs_attention` is true when the chart is
|
|
11684
|
+
not fully applied — something is waiting on a person, whether an approval,
|
|
11685
|
+
an OAuth sign-in, or a resource that drifted and was left alone.
|
|
11686
|
+
|
|
11687
|
+
Save `applied_state` to `.1claw/apply-state.json`. It records what apply
|
|
11688
|
+
set, which is what lets the next run tell drift from a first apply.
|
|
11689
|
+
|
|
11690
|
+
v1 creates and reports; it does not delete, prune, or patch in place. An
|
|
11691
|
+
apply that silently deletes is an apply nobody runs twice.
|
|
11692
|
+
operationId: applyChart
|
|
11693
|
+
requestBody:
|
|
11694
|
+
required: true
|
|
11695
|
+
content:
|
|
11696
|
+
application/json:
|
|
11697
|
+
schema:
|
|
11698
|
+
type: object
|
|
11699
|
+
required: [chart]
|
|
11700
|
+
properties:
|
|
11701
|
+
chart:
|
|
11702
|
+
type: object
|
|
11703
|
+
description: A chart document — `apiVersion`, `kind`, `metadata`, `spec`.
|
|
11704
|
+
applied_state:
|
|
11705
|
+
type: object
|
|
11706
|
+
additionalProperties: true
|
|
11707
|
+
responses:
|
|
11708
|
+
"200":
|
|
11709
|
+
description: What happened to each resource
|
|
11710
|
+
content:
|
|
11711
|
+
application/json:
|
|
11712
|
+
schema:
|
|
11713
|
+
type: object
|
|
11714
|
+
properties:
|
|
11715
|
+
chart_name: { type: string }
|
|
11716
|
+
resources:
|
|
11717
|
+
type: array
|
|
11718
|
+
items:
|
|
11719
|
+
type: object
|
|
11720
|
+
properties:
|
|
11721
|
+
kind: { type: string }
|
|
11722
|
+
name: { type: string }
|
|
11723
|
+
result:
|
|
11724
|
+
type: string
|
|
11725
|
+
enum: [created, unchanged, skipped, refused, awaiting_approval, failed]
|
|
11726
|
+
id: { type: string, format: uuid }
|
|
11727
|
+
detail: { type: string }
|
|
11728
|
+
warnings:
|
|
11729
|
+
type: array
|
|
11730
|
+
items: { type: string }
|
|
11731
|
+
applied_state:
|
|
11732
|
+
type: object
|
|
11733
|
+
additionalProperties: true
|
|
11734
|
+
description: Save to `.1claw/apply-state.json`.
|
|
11735
|
+
needs_attention:
|
|
11736
|
+
type: boolean
|
|
11737
|
+
description: The chart is not fully applied — something is waiting on a person.
|
|
11738
|
+
"400":
|
|
11739
|
+
$ref: "#/components/responses/BadRequest"
|
|
11740
|
+
"403":
|
|
11741
|
+
$ref: "#/components/responses/Forbidden"
|
|
11742
|
+
|
|
11743
|
+
/v1/org/approval-learning/shadow-report:
|
|
11744
|
+
get:
|
|
11745
|
+
tags: [Organization]
|
|
11746
|
+
summary: What would have been approved automatically
|
|
11747
|
+
description: |
|
|
11748
|
+
Every approval decision is observed, per **fingerprint bucket** — the
|
|
11749
|
+
action, the amount band, whether the recipient was new, and who they
|
|
11750
|
+
were. This reports the buckets a person has approved without exception,
|
|
11751
|
+
and what promoting one would write into an agent's policy.
|
|
11752
|
+
|
|
11753
|
+
Observing is not acting. In the default `shadow` mode nothing changes who
|
|
11754
|
+
gets asked; `can_promote` is false and the promote endpoint refuses.
|
|
11755
|
+
|
|
11756
|
+
Each suggestion carries `would_write_rule` — the actual rule, built by the
|
|
11757
|
+
same function promotion uses, so the report cannot promise something
|
|
11758
|
+
promotion would refuse.
|
|
11759
|
+
operationId: getApprovalLearningShadowReport
|
|
11760
|
+
responses:
|
|
11761
|
+
"200":
|
|
11762
|
+
description: Report
|
|
11763
|
+
content:
|
|
11764
|
+
application/json:
|
|
11765
|
+
schema:
|
|
11766
|
+
type: object
|
|
11767
|
+
properties:
|
|
11768
|
+
mode: { type: string, enum: [shadow, enforce] }
|
|
11769
|
+
threshold:
|
|
11770
|
+
type: integer
|
|
11771
|
+
description: Consecutive approvals in one bucket before it appears here.
|
|
11772
|
+
can_promote: { type: boolean }
|
|
11773
|
+
observed_buckets: { type: integer }
|
|
11774
|
+
total_decisions: { type: integer }
|
|
11775
|
+
suggestions:
|
|
11776
|
+
type: array
|
|
11777
|
+
items:
|
|
11778
|
+
type: object
|
|
11779
|
+
properties:
|
|
11780
|
+
profile_id: { type: string, format: uuid }
|
|
11781
|
+
action_type: { type: string }
|
|
11782
|
+
fingerprint_bucket: { type: string, example: "refund.create|0-10|known|a@b.co" }
|
|
11783
|
+
consecutive_approvals: { type: integer }
|
|
11784
|
+
total_requests: { type: integer }
|
|
11785
|
+
would_write_rule: { type: object, nullable: true }
|
|
11786
|
+
blocked:
|
|
11787
|
+
type: string
|
|
11788
|
+
description: Present when a bound prevents promotion, saying which.
|
|
11789
|
+
last_decision_at: { type: string, format: date-time }
|
|
11790
|
+
"403":
|
|
11791
|
+
$ref: "#/components/responses/Forbidden"
|
|
11792
|
+
|
|
11793
|
+
/v1/org/approval-learning/{profile_id}/promote:
|
|
11794
|
+
post:
|
|
11795
|
+
tags: [Organization]
|
|
11796
|
+
summary: Turn an observed pattern into a policy rule
|
|
11797
|
+
description: |
|
|
11798
|
+
Writes a rule into the named agent's `action_approval_policy`. Human users
|
|
11799
|
+
only, and only when the organisation is in `enforce` mode.
|
|
11800
|
+
|
|
11801
|
+
**The rule covers only what was actually approved.** Five approved $5
|
|
11802
|
+
refunds to one customer produce `{ refund.create, asks above $10, that
|
|
11803
|
+
recipient }` — a $49 request does not match it and still reaches a human.
|
|
11804
|
+
|
|
11805
|
+
Refused when: fewer than five consecutive approvals; *any* past rejection
|
|
11806
|
+
on the bucket (a long recent run must not hide a history of refusals); the
|
|
11807
|
+
bucket is for a recipient never paid before; the amount band has no upper
|
|
11808
|
+
edge; or the action grants or destroys authority.
|
|
11809
|
+
|
|
11810
|
+
`widen_to_action_type` drops the amount and recipient constraints. It is
|
|
11811
|
+
never the default and should be an explicit choice in your UI, not a
|
|
11812
|
+
checkbox someone skims past.
|
|
11813
|
+
|
|
11814
|
+
The written rule is marked `promoted_from_learning` so an operator can
|
|
11815
|
+
tell it apart from one they wrote, and it replaces any existing rule for
|
|
11816
|
+
the same action type — appending would leave two rules where only the
|
|
11817
|
+
first ever applies.
|
|
11818
|
+
operationId: promoteApprovalLearningProfile
|
|
11819
|
+
parameters:
|
|
11820
|
+
- name: profile_id
|
|
11821
|
+
in: path
|
|
11822
|
+
required: true
|
|
11823
|
+
schema: { type: string, format: uuid }
|
|
11824
|
+
requestBody:
|
|
11825
|
+
required: true
|
|
11826
|
+
content:
|
|
11827
|
+
application/json:
|
|
11828
|
+
schema:
|
|
11829
|
+
type: object
|
|
11830
|
+
required: [agent_id]
|
|
11831
|
+
properties:
|
|
11832
|
+
agent_id: { type: string, format: uuid }
|
|
11833
|
+
widen_to_action_type:
|
|
11834
|
+
type: boolean
|
|
11835
|
+
default: false
|
|
11836
|
+
responses:
|
|
11837
|
+
"200":
|
|
11838
|
+
description: Promoted
|
|
11839
|
+
content:
|
|
11840
|
+
application/json:
|
|
11841
|
+
schema:
|
|
11842
|
+
type: object
|
|
11843
|
+
properties:
|
|
11844
|
+
profile_id: { type: string, format: uuid }
|
|
11845
|
+
agent_id: { type: string, format: uuid }
|
|
11846
|
+
rule: { type: object }
|
|
11847
|
+
"400":
|
|
11848
|
+
$ref: "#/components/responses/BadRequest"
|
|
11849
|
+
"403":
|
|
11850
|
+
$ref: "#/components/responses/Forbidden"
|
|
11851
|
+
"404":
|
|
11852
|
+
$ref: "#/components/responses/NotFound"
|
|
11853
|
+
"409":
|
|
11854
|
+
$ref: "#/components/responses/Conflict"
|
|
11855
|
+
|
|
11856
|
+
/v1/policy-presets:
|
|
11857
|
+
get:
|
|
11858
|
+
tags: [Policies]
|
|
11859
|
+
summary: Named starting points for an agent's policy
|
|
11860
|
+
description: |
|
|
11861
|
+
Four presets an operator can choose between without reading a policy
|
|
11862
|
+
document. Public — a description of what 1Claw offers, not tenant data.
|
|
11863
|
+
|
|
11864
|
+
Each carries a `headline`: the one-line consequence someone should read
|
|
11865
|
+
before choosing it, in the words they would use.
|
|
11866
|
+
operationId: listPolicyPresets
|
|
11245
11867
|
security: []
|
|
11868
|
+
responses:
|
|
11869
|
+
"200":
|
|
11870
|
+
description: Catalogue
|
|
11871
|
+
content:
|
|
11872
|
+
application/json:
|
|
11873
|
+
schema:
|
|
11874
|
+
type: object
|
|
11875
|
+
properties:
|
|
11876
|
+
presets: { type: array, items: { type: object } }
|
|
11877
|
+
|
|
11878
|
+
/v1/agents/{agent_id}/policy-preset/preview:
|
|
11879
|
+
post:
|
|
11880
|
+
tags: [Policies]
|
|
11881
|
+
summary: What a preset would change
|
|
11882
|
+
description: |
|
|
11883
|
+
Compiles a preset against this agent and reports which fields it would
|
|
11884
|
+
**widen** — loosen relative to what the agent can already do.
|
|
11885
|
+
|
|
11886
|
+
Widening detection errs toward flagging: a false positive costs one extra
|
|
11887
|
+
approval, a false negative is a limit raised without review. Enabling a
|
|
11888
|
+
capability widens; disabling does not. Raising a cap widens; setting a
|
|
11889
|
+
first cap does not, because absent means unlimited.
|
|
11890
|
+
operationId: previewPolicyPreset
|
|
11246
11891
|
parameters:
|
|
11247
|
-
- name:
|
|
11892
|
+
- name: agent_id
|
|
11248
11893
|
in: path
|
|
11249
11894
|
required: true
|
|
11250
|
-
schema:
|
|
11251
|
-
type: string
|
|
11895
|
+
schema: { type: string, format: uuid }
|
|
11252
11896
|
requestBody:
|
|
11253
11897
|
required: true
|
|
11254
11898
|
content:
|
|
11255
11899
|
application/json:
|
|
11256
11900
|
schema:
|
|
11257
11901
|
type: object
|
|
11902
|
+
required: [preset]
|
|
11903
|
+
properties:
|
|
11904
|
+
preset: { type: string, example: small-business-spender }
|
|
11258
11905
|
responses:
|
|
11259
11906
|
"200":
|
|
11260
|
-
description:
|
|
11907
|
+
description: Proposal
|
|
11908
|
+
content:
|
|
11909
|
+
application/json:
|
|
11910
|
+
schema:
|
|
11911
|
+
type: object
|
|
11912
|
+
properties:
|
|
11913
|
+
preset_slug: { type: string }
|
|
11914
|
+
guardrails: { type: object }
|
|
11915
|
+
action_approval_policy: { type: object }
|
|
11916
|
+
access_policy: { type: object }
|
|
11917
|
+
widens:
|
|
11918
|
+
type: array
|
|
11919
|
+
items: { type: string }
|
|
11920
|
+
description: Fields this preset would loosen. Show these, not a generic warning.
|
|
11921
|
+
requires_guardrail_approval: { type: boolean }
|
|
11922
|
+
explanation: { type: string }
|
|
11923
|
+
"403":
|
|
11924
|
+
$ref: "#/components/responses/Forbidden"
|
|
11925
|
+
"404":
|
|
11926
|
+
$ref: "#/components/responses/NotFound"
|
|
11261
11927
|
|
|
11262
|
-
|
|
11263
|
-
|
|
11264
|
-
|
|
11928
|
+
/v1/agents/{agent_id}/policy-preset:
|
|
11929
|
+
post:
|
|
11930
|
+
tags: [Policies]
|
|
11931
|
+
summary: Apply a policy preset
|
|
11932
|
+
description: |
|
|
11933
|
+
**Applies through the agent update handler**, not by writing guardrail
|
|
11934
|
+
columns. A preset that wrote them directly would be a way around the
|
|
11935
|
+
guardrail widening approval flow wearing a friendlier interface.
|
|
11265
11936
|
|
|
11266
|
-
|
|
11937
|
+
So if the preset loosens something and your organisation gates that, you
|
|
11938
|
+
get the same **202 with a pending approval** you would get from editing
|
|
11939
|
+
the agent by hand — not a quietly applied change. Pass `approval_id`
|
|
11940
|
+
once that approval is granted.
|
|
11941
|
+
operationId: applyPolicyPreset
|
|
11942
|
+
parameters:
|
|
11943
|
+
- name: agent_id
|
|
11944
|
+
in: path
|
|
11945
|
+
required: true
|
|
11946
|
+
schema: { type: string, format: uuid }
|
|
11947
|
+
requestBody:
|
|
11948
|
+
required: true
|
|
11949
|
+
content:
|
|
11950
|
+
application/json:
|
|
11951
|
+
schema:
|
|
11952
|
+
type: object
|
|
11953
|
+
required: [preset]
|
|
11954
|
+
properties:
|
|
11955
|
+
preset: { type: string }
|
|
11956
|
+
approval_id: { type: string, format: uuid }
|
|
11957
|
+
responses:
|
|
11958
|
+
"200":
|
|
11959
|
+
description: Applied
|
|
11960
|
+
"202":
|
|
11961
|
+
description: Queued behind a guardrail approval
|
|
11962
|
+
"403":
|
|
11963
|
+
$ref: "#/components/responses/Forbidden"
|
|
11964
|
+
"404":
|
|
11965
|
+
$ref: "#/components/responses/NotFound"
|
|
11966
|
+
|
|
11967
|
+
/v1/agents/{agent_id}/trust:
|
|
11267
11968
|
get:
|
|
11268
|
-
tags: [
|
|
11269
|
-
summary:
|
|
11969
|
+
tags: [Discovery]
|
|
11970
|
+
summary: What a listed agent has earned
|
|
11270
11971
|
description: |
|
|
11271
|
-
|
|
11272
|
-
|
|
11273
|
-
|
|
11972
|
+
Everything a publisher writes — name, description, tags — is a claim.
|
|
11973
|
+
These are the parts they cannot write: whether a human reviewed the
|
|
11974
|
+
listing, how many people installed it, what they rated it.
|
|
11975
|
+
|
|
11976
|
+
Public, because its purpose is to be read by someone deciding whether to
|
|
11977
|
+
install a stranger's agent. Only listed agents have public trust.
|
|
11978
|
+
|
|
11979
|
+
**A listing with reports shows no badges at all.** "Platform reviewed"
|
|
11980
|
+
beside an active complaint tells a reader the opposite of what they need.
|
|
11981
|
+
An average rating appears only from three reviews — one rating is not an
|
|
11982
|
+
average.
|
|
11983
|
+
operationId: getAgentTrust
|
|
11274
11984
|
security: []
|
|
11985
|
+
parameters:
|
|
11986
|
+
- name: agent_id
|
|
11987
|
+
in: path
|
|
11988
|
+
required: true
|
|
11989
|
+
schema: { type: string, format: uuid }
|
|
11275
11990
|
responses:
|
|
11276
11991
|
"200":
|
|
11277
|
-
description:
|
|
11992
|
+
description: Trust signals
|
|
11278
11993
|
content:
|
|
11279
11994
|
application/json:
|
|
11280
11995
|
schema:
|
|
11281
|
-
|
|
11996
|
+
type: object
|
|
11997
|
+
properties:
|
|
11998
|
+
trust:
|
|
11999
|
+
type: object
|
|
12000
|
+
properties:
|
|
12001
|
+
tier: { type: string, enum: [unverified, platform_reviewed, identity_verified, enterprise] }
|
|
12002
|
+
install_count: { type: integer }
|
|
12003
|
+
avg_rating: { type: number, nullable: true }
|
|
12004
|
+
review_count: { type: integer }
|
|
12005
|
+
badges: { type: array, items: { type: string } }
|
|
12006
|
+
flagged_for_review: { type: boolean }
|
|
12007
|
+
"404":
|
|
12008
|
+
$ref: "#/components/responses/NotFound"
|
|
12009
|
+
|
|
12010
|
+
/v1/agents/{agent_id}/report:
|
|
12011
|
+
post:
|
|
12012
|
+
tags: [Discovery]
|
|
12013
|
+
summary: Report a listed agent
|
|
12014
|
+
description: |
|
|
12015
|
+
Human users only — an agent reporting another agent is a way to bury a
|
|
12016
|
+
competitor's listing at machine speed.
|
|
12017
|
+
|
|
12018
|
+
The response does not include the report count. Telling a reporter how
|
|
12019
|
+
close a listing is to being flagged tells them how many more to file.
|
|
12020
|
+
operationId: reportAgent
|
|
12021
|
+
parameters:
|
|
12022
|
+
- name: agent_id
|
|
12023
|
+
in: path
|
|
12024
|
+
required: true
|
|
12025
|
+
schema: { type: string, format: uuid }
|
|
12026
|
+
requestBody:
|
|
12027
|
+
required: true
|
|
12028
|
+
content:
|
|
12029
|
+
application/json:
|
|
12030
|
+
schema:
|
|
12031
|
+
type: object
|
|
12032
|
+
properties:
|
|
12033
|
+
reason: { type: string }
|
|
12034
|
+
responses:
|
|
12035
|
+
"202":
|
|
12036
|
+
description: Received
|
|
12037
|
+
"403":
|
|
12038
|
+
$ref: "#/components/responses/Forbidden"
|
|
12039
|
+
"404":
|
|
12040
|
+
$ref: "#/components/responses/NotFound"
|
|
12041
|
+
|
|
12042
|
+
/v1/agents/{agent_id}/review:
|
|
12043
|
+
post:
|
|
12044
|
+
tags: [Discovery]
|
|
12045
|
+
summary: Rate an agent you have used
|
|
12046
|
+
description: |
|
|
12047
|
+
One review per person per agent; a second replaces the first. You cannot
|
|
12048
|
+
review an agent from your own organisation.
|
|
12049
|
+
|
|
12050
|
+
Comments are shown only once moderated. The rating counts either way — a
|
|
12051
|
+
number is harder to abuse than free text.
|
|
12052
|
+
operationId: reviewAgent
|
|
12053
|
+
parameters:
|
|
12054
|
+
- name: agent_id
|
|
12055
|
+
in: path
|
|
12056
|
+
required: true
|
|
12057
|
+
schema: { type: string, format: uuid }
|
|
12058
|
+
requestBody:
|
|
12059
|
+
required: true
|
|
12060
|
+
content:
|
|
12061
|
+
application/json:
|
|
12062
|
+
schema:
|
|
12063
|
+
type: object
|
|
12064
|
+
required: [rating]
|
|
12065
|
+
properties:
|
|
12066
|
+
rating: { type: integer, minimum: 1, maximum: 5 }
|
|
12067
|
+
comment: { type: string }
|
|
12068
|
+
responses:
|
|
12069
|
+
"201":
|
|
12070
|
+
description: Recorded
|
|
12071
|
+
"400":
|
|
12072
|
+
$ref: "#/components/responses/BadRequest"
|
|
12073
|
+
"403":
|
|
12074
|
+
$ref: "#/components/responses/Forbidden"
|
|
12075
|
+
"404":
|
|
12076
|
+
$ref: "#/components/responses/NotFound"
|
|
12077
|
+
|
|
12078
|
+
/v1/peers:
|
|
12079
|
+
post:
|
|
12080
|
+
tags: [Memory]
|
|
12081
|
+
summary: Create a peer and name its observers
|
|
12082
|
+
description: |
|
|
12083
|
+
Human users only. Creating a peer decides which agents may read a model
|
|
12084
|
+
of a person, and an agent that could do that could add itself.
|
|
12085
|
+
|
|
12086
|
+
Idempotent on `(org, peer_type, peer_ref)`. Observers are **merged**, not
|
|
12087
|
+
replaced — a second call adding one agent does not revoke the others
|
|
12088
|
+
already watching. Every named observer must be an agent in this
|
|
12089
|
+
organisation, so a typo or an id copied from elsewhere is an error rather
|
|
12090
|
+
than a silent no-op that leaves an operator believing an agent is
|
|
12091
|
+
watching when none is.
|
|
12092
|
+
operationId: createPeer
|
|
12093
|
+
requestBody:
|
|
12094
|
+
required: true
|
|
12095
|
+
content:
|
|
12096
|
+
application/json:
|
|
12097
|
+
schema:
|
|
12098
|
+
type: object
|
|
12099
|
+
required: [peer_type, peer_ref]
|
|
12100
|
+
properties:
|
|
12101
|
+
peer_type: { type: string, enum: [user, platform_connection, external] }
|
|
12102
|
+
peer_ref: { type: string }
|
|
12103
|
+
display_name: { type: string }
|
|
12104
|
+
platform_connection_id: { type: string, format: uuid }
|
|
12105
|
+
observer_agent_ids:
|
|
12106
|
+
type: array
|
|
12107
|
+
items: { type: string, format: uuid }
|
|
12108
|
+
description: Empty means nobody. A peer with no observers is readable by no agent.
|
|
12109
|
+
responses:
|
|
12110
|
+
"201":
|
|
12111
|
+
description: Peer created or updated
|
|
12112
|
+
content:
|
|
12113
|
+
application/json:
|
|
12114
|
+
schema:
|
|
12115
|
+
type: object
|
|
12116
|
+
properties:
|
|
12117
|
+
peer: { $ref: "#/components/schemas/Peer" }
|
|
12118
|
+
"400":
|
|
12119
|
+
$ref: "#/components/responses/BadRequest"
|
|
12120
|
+
"403":
|
|
12121
|
+
$ref: "#/components/responses/Forbidden"
|
|
12122
|
+
|
|
12123
|
+
/v1/peers/{peer_id}/export:
|
|
12124
|
+
get:
|
|
12125
|
+
tags: [Memory]
|
|
12126
|
+
summary: Everything held about this person
|
|
12127
|
+
description: |
|
|
12128
|
+
The whole behavioural profile plus the raw observations behind it. Human
|
|
12129
|
+
users only, behind strong-factor re-auth — this is exactly what a stolen
|
|
12130
|
+
session would want.
|
|
12131
|
+
|
|
12132
|
+
Each fact carries `why_we_believe_this`: its provenance, including
|
|
12133
|
+
tombstones for observations that have since expired. An export listing
|
|
12134
|
+
conclusions without their basis answers only the easy half of the
|
|
12135
|
+
question.
|
|
12136
|
+
operationId: exportPeerData
|
|
12137
|
+
parameters:
|
|
12138
|
+
- name: peer_id
|
|
12139
|
+
in: path
|
|
12140
|
+
required: true
|
|
12141
|
+
schema: { type: string, format: uuid }
|
|
12142
|
+
responses:
|
|
12143
|
+
"200":
|
|
12144
|
+
description: Export
|
|
12145
|
+
content:
|
|
12146
|
+
application/json:
|
|
12147
|
+
schema:
|
|
12148
|
+
type: object
|
|
12149
|
+
properties:
|
|
12150
|
+
peer: { type: object }
|
|
12151
|
+
facts:
|
|
12152
|
+
type: array
|
|
12153
|
+
items:
|
|
12154
|
+
type: object
|
|
12155
|
+
properties:
|
|
12156
|
+
fact_key: { type: string }
|
|
12157
|
+
fact_value: { type: object }
|
|
12158
|
+
confidence: { type: string, nullable: true }
|
|
12159
|
+
why_we_believe_this: { type: array, items: { type: object } }
|
|
12160
|
+
corrected_by_a_human: { type: boolean }
|
|
12161
|
+
raw_observations: { type: array, items: { type: object } }
|
|
12162
|
+
note: { type: string }
|
|
12163
|
+
"403":
|
|
12164
|
+
$ref: "#/components/responses/Forbidden"
|
|
12165
|
+
"404":
|
|
12166
|
+
$ref: "#/components/responses/NotFound"
|
|
12167
|
+
|
|
12168
|
+
/v1/peers/{peer_id}/data:
|
|
12169
|
+
delete:
|
|
12170
|
+
tags: [Memory]
|
|
12171
|
+
summary: Forget this person
|
|
12172
|
+
description: |
|
|
12173
|
+
Deletes the peer, its facts and its observations. Human users only,
|
|
12174
|
+
behind strong-factor re-auth, and irreversible.
|
|
12175
|
+
|
|
12176
|
+
Returns counts of what was removed — "deleted" with no numbers is not
|
|
12177
|
+
something anyone can check. The audit entry records that a deletion
|
|
12178
|
+
happened and deliberately omits the identifier someone asked to have
|
|
12179
|
+
forgotten.
|
|
12180
|
+
operationId: deletePeerData
|
|
12181
|
+
parameters:
|
|
12182
|
+
- name: peer_id
|
|
12183
|
+
in: path
|
|
12184
|
+
required: true
|
|
12185
|
+
schema: { type: string, format: uuid }
|
|
12186
|
+
responses:
|
|
12187
|
+
"200":
|
|
12188
|
+
description: Deleted
|
|
12189
|
+
content:
|
|
12190
|
+
application/json:
|
|
12191
|
+
schema:
|
|
12192
|
+
type: object
|
|
12193
|
+
properties:
|
|
12194
|
+
deleted: { type: boolean }
|
|
12195
|
+
facts_deleted: { type: integer }
|
|
12196
|
+
observations_deleted: { type: integer }
|
|
12197
|
+
"403":
|
|
12198
|
+
$ref: "#/components/responses/Forbidden"
|
|
12199
|
+
"404":
|
|
12200
|
+
$ref: "#/components/responses/NotFound"
|
|
12201
|
+
|
|
12202
|
+
/v1/peers/{peer_id}/facts:
|
|
12203
|
+
patch:
|
|
12204
|
+
tags: [Memory]
|
|
12205
|
+
summary: Correct what the system believes
|
|
12206
|
+
description: |
|
|
12207
|
+
Human users only. A correction **pins** the fact: the background
|
|
12208
|
+
processor will not re-derive over it, because someone correcting what a
|
|
12209
|
+
system believes about them outranks the inference that got it wrong.
|
|
12210
|
+
|
|
12211
|
+
The correction is appended to the fact's provenance as a `human` entry,
|
|
12212
|
+
so the record shows both what was inferred and that a person disagreed.
|
|
12213
|
+
operationId: editPeerFact
|
|
12214
|
+
parameters:
|
|
12215
|
+
- name: peer_id
|
|
12216
|
+
in: path
|
|
12217
|
+
required: true
|
|
12218
|
+
schema: { type: string, format: uuid }
|
|
12219
|
+
requestBody:
|
|
12220
|
+
required: true
|
|
12221
|
+
content:
|
|
12222
|
+
application/json:
|
|
12223
|
+
schema:
|
|
12224
|
+
type: object
|
|
12225
|
+
required: [fact_key, fact_value]
|
|
12226
|
+
properties:
|
|
12227
|
+
fact_key: { type: string }
|
|
12228
|
+
fact_value: { type: object }
|
|
12229
|
+
responses:
|
|
12230
|
+
"200":
|
|
12231
|
+
description: Corrected
|
|
12232
|
+
content:
|
|
12233
|
+
application/json:
|
|
12234
|
+
schema:
|
|
12235
|
+
type: object
|
|
12236
|
+
properties:
|
|
12237
|
+
fact_key: { type: string }
|
|
12238
|
+
edited_by_human: { type: boolean }
|
|
12239
|
+
note: { type: string }
|
|
12240
|
+
"403":
|
|
12241
|
+
$ref: "#/components/responses/Forbidden"
|
|
12242
|
+
"404":
|
|
12243
|
+
$ref: "#/components/responses/NotFound"
|
|
12244
|
+
|
|
12245
|
+
/v1/peers/{peer_id}/context:
|
|
12246
|
+
get:
|
|
12247
|
+
tags: [Memory]
|
|
12248
|
+
summary: A context blob for prompt injection
|
|
12249
|
+
description: |
|
|
12250
|
+
What this person's history suggests, as prose an agent can put in a
|
|
12251
|
+
prompt. Best-supported facts first, so a tight budget drops the
|
|
12252
|
+
least-supported beliefs rather than an arbitrary tail — and a fact a
|
|
12253
|
+
human corrected sorts ahead of everything, because a correction someone
|
|
12254
|
+
took the trouble to make is the last thing to cut.
|
|
12255
|
+
|
|
12256
|
+
Never truncates mid-line: half a sentence about a person is worse than
|
|
12257
|
+
one fewer sentence. A peer with no facts returns an empty string rather
|
|
12258
|
+
than a header claiming to describe someone.
|
|
12259
|
+
|
|
12260
|
+
The blob ends by saying these are observations and not instructions,
|
|
12261
|
+
because an agent reading it needs to know the difference.
|
|
12262
|
+
operationId: getPeerContext
|
|
12263
|
+
parameters:
|
|
12264
|
+
- name: peer_id
|
|
12265
|
+
in: path
|
|
12266
|
+
required: true
|
|
12267
|
+
schema: { type: string, format: uuid }
|
|
12268
|
+
- name: budget
|
|
12269
|
+
in: query
|
|
12270
|
+
description: Characters. Default 2000, capped at 8000.
|
|
12271
|
+
schema: { type: integer }
|
|
12272
|
+
responses:
|
|
12273
|
+
"200":
|
|
12274
|
+
description: Context
|
|
12275
|
+
content:
|
|
12276
|
+
application/json:
|
|
12277
|
+
schema:
|
|
12278
|
+
type: object
|
|
12279
|
+
properties:
|
|
12280
|
+
context: { type: string }
|
|
12281
|
+
characters: { type: integer }
|
|
12282
|
+
budget: { type: integer }
|
|
12283
|
+
facts_available: { type: integer }
|
|
12284
|
+
"403":
|
|
12285
|
+
$ref: "#/components/responses/Forbidden"
|
|
12286
|
+
"404":
|
|
12287
|
+
$ref: "#/components/responses/NotFound"
|
|
12288
|
+
|
|
12289
|
+
/v1/agents/{agent_id}/peer-context:
|
|
12290
|
+
get:
|
|
12291
|
+
tags: [Memory]
|
|
12292
|
+
summary: An agent's own peer context
|
|
12293
|
+
description: |
|
|
12294
|
+
Resolves the peer from the agent's platform connection, so an agent does
|
|
12295
|
+
not need to know a peer id.
|
|
12296
|
+
|
|
12297
|
+
An agent may only ask for its own — otherwise this route would be a way
|
|
12298
|
+
to read a peer through an agent that observes it, from one that does not.
|
|
12299
|
+
The observer check still applies: being the agent named in the path is
|
|
12300
|
+
not the same as observing that connection's peer.
|
|
12301
|
+
operationId: getAgentPeerContext
|
|
12302
|
+
parameters:
|
|
12303
|
+
- name: agent_id
|
|
12304
|
+
in: path
|
|
12305
|
+
required: true
|
|
12306
|
+
schema: { type: string, format: uuid }
|
|
12307
|
+
- name: budget
|
|
12308
|
+
in: query
|
|
12309
|
+
schema: { type: integer }
|
|
12310
|
+
responses:
|
|
12311
|
+
"200":
|
|
12312
|
+
description: Context
|
|
12313
|
+
content:
|
|
12314
|
+
application/json:
|
|
12315
|
+
schema:
|
|
12316
|
+
type: object
|
|
12317
|
+
properties:
|
|
12318
|
+
peer_id: { type: string, format: uuid }
|
|
12319
|
+
context: { type: string }
|
|
12320
|
+
characters: { type: integer }
|
|
12321
|
+
"403":
|
|
12322
|
+
$ref: "#/components/responses/Forbidden"
|
|
12323
|
+
"404":
|
|
12324
|
+
$ref: "#/components/responses/NotFound"
|
|
12325
|
+
|
|
12326
|
+
/v1/peers/{peer_id}:
|
|
12327
|
+
get:
|
|
12328
|
+
tags: [Memory]
|
|
12329
|
+
summary: A peer's profile and derived facts
|
|
12330
|
+
description: |
|
|
12331
|
+
A peer is a shared model of one human, across the agents serving them.
|
|
12332
|
+
|
|
12333
|
+
**An agent reaches a peer only by being named in its observer list.**
|
|
12334
|
+
Being in the same organisation, the same platform connection, or holding
|
|
12335
|
+
a broad scope grants nothing. A peer with no observers is readable by no
|
|
12336
|
+
agent at all — forgetting to set observers must not expose someone's
|
|
12337
|
+
behavioural profile to every agent in the org.
|
|
12338
|
+
|
|
12339
|
+
A peer in another organisation returns 404, the same as an unknown id:
|
|
12340
|
+
whether one exists elsewhere is not something a caller should learn.
|
|
12341
|
+
|
|
12342
|
+
Each fact carries `provenance` — why it is believed. Entries for events
|
|
12343
|
+
that have since expired become tombstones keeping the shape of what was
|
|
12344
|
+
seen without the content, so a belief about a person always has a
|
|
12345
|
+
recoverable basis.
|
|
12346
|
+
operationId: getPeer
|
|
12347
|
+
parameters:
|
|
12348
|
+
- name: peer_id
|
|
12349
|
+
in: path
|
|
12350
|
+
required: true
|
|
12351
|
+
schema: { type: string, format: uuid }
|
|
12352
|
+
responses:
|
|
12353
|
+
"200":
|
|
12354
|
+
description: Peer and facts
|
|
12355
|
+
content:
|
|
12356
|
+
application/json:
|
|
12357
|
+
schema:
|
|
12358
|
+
type: object
|
|
12359
|
+
properties:
|
|
12360
|
+
peer: { $ref: "#/components/schemas/Peer" }
|
|
12361
|
+
facts:
|
|
12362
|
+
type: array
|
|
12363
|
+
items: { $ref: "#/components/schemas/PeerFact" }
|
|
12364
|
+
"403":
|
|
12365
|
+
$ref: "#/components/responses/Forbidden"
|
|
12366
|
+
"404":
|
|
12367
|
+
$ref: "#/components/responses/NotFound"
|
|
12368
|
+
|
|
12369
|
+
/v1/peers/{peer_id}/events:
|
|
12370
|
+
post:
|
|
12371
|
+
tags: [Memory]
|
|
12372
|
+
summary: Record something observed about a person
|
|
12373
|
+
operationId: recordPeerEvent
|
|
12374
|
+
parameters:
|
|
12375
|
+
- name: peer_id
|
|
12376
|
+
in: path
|
|
12377
|
+
required: true
|
|
12378
|
+
schema: { type: string, format: uuid }
|
|
12379
|
+
requestBody:
|
|
12380
|
+
required: true
|
|
12381
|
+
content:
|
|
12382
|
+
application/json:
|
|
12383
|
+
schema:
|
|
12384
|
+
type: object
|
|
12385
|
+
required: [event_type, content]
|
|
12386
|
+
properties:
|
|
12387
|
+
event_type:
|
|
12388
|
+
type: string
|
|
12389
|
+
enum: [message, approval, action, observation]
|
|
12390
|
+
content: { type: object, additionalProperties: true }
|
|
12391
|
+
responses:
|
|
12392
|
+
"201":
|
|
12393
|
+
description: Recorded
|
|
12394
|
+
content:
|
|
12395
|
+
application/json:
|
|
12396
|
+
schema:
|
|
12397
|
+
type: object
|
|
12398
|
+
properties:
|
|
12399
|
+
event_id: { type: string, format: uuid }
|
|
12400
|
+
"400":
|
|
12401
|
+
$ref: "#/components/responses/BadRequest"
|
|
12402
|
+
"403":
|
|
12403
|
+
$ref: "#/components/responses/Forbidden"
|
|
12404
|
+
"404":
|
|
12405
|
+
$ref: "#/components/responses/NotFound"
|
|
12406
|
+
|
|
12407
|
+
/v1/peers/{peer_id}/predict-approval:
|
|
12408
|
+
post:
|
|
12409
|
+
tags: [Memory]
|
|
12410
|
+
summary: How has this person decided this before?
|
|
12411
|
+
description: |
|
|
12412
|
+
Answers two different questions, and keeps them apart on purpose.
|
|
12413
|
+
|
|
12414
|
+
`likelihood` is an **observation about a person** — how they have decided
|
|
12415
|
+
comparable requests before. Comparable means the same fingerprint bucket,
|
|
12416
|
+
not the same action type: three approvals of $5 say nothing about $500.
|
|
12417
|
+
|
|
12418
|
+
`suggest_auto` is a **statement about a policy**. It is true only where a
|
|
12419
|
+
rule the operator already wrote would auto-approve this exact case. It is
|
|
12420
|
+
never derived from `likelihood`, and a confident model never becomes new
|
|
12421
|
+
authority. It is false, with `blocked_reason`, when:
|
|
12422
|
+
|
|
12423
|
+
* no rule covers the action (`no_matching_rule`);
|
|
12424
|
+
* a rule says a human decides (`rule_requires_approval`);
|
|
12425
|
+
* the amount is above the rule's own threshold (`above_configured_threshold`);
|
|
12426
|
+
* the derived risk tier is above the lowest (`risk_tier_requires_step_up`);
|
|
12427
|
+
* the action grants or destroys authority (`action_is_sensitive`).
|
|
12428
|
+
|
|
12429
|
+
The policy consulted is the calling agent's own, so a prediction cannot
|
|
12430
|
+
inherit authority from another agent that happens to observe the same
|
|
12431
|
+
person.
|
|
12432
|
+
operationId: predictApproval
|
|
12433
|
+
parameters:
|
|
12434
|
+
- name: peer_id
|
|
12435
|
+
in: path
|
|
12436
|
+
required: true
|
|
12437
|
+
schema: { type: string, format: uuid }
|
|
12438
|
+
requestBody:
|
|
12439
|
+
required: true
|
|
12440
|
+
content:
|
|
12441
|
+
application/json:
|
|
12442
|
+
schema:
|
|
12443
|
+
type: object
|
|
12444
|
+
required: [action_type, effective_risk_tier]
|
|
12445
|
+
properties:
|
|
12446
|
+
action_type: { type: string, example: refund.create }
|
|
12447
|
+
payload: { type: object, additionalProperties: true }
|
|
12448
|
+
effective_risk_tier:
|
|
12449
|
+
type: integer
|
|
12450
|
+
minimum: 1
|
|
12451
|
+
maximum: 3
|
|
12452
|
+
responses:
|
|
12453
|
+
"200":
|
|
12454
|
+
description: Prediction
|
|
12455
|
+
content:
|
|
12456
|
+
application/json:
|
|
12457
|
+
schema:
|
|
12458
|
+
type: object
|
|
12459
|
+
required: [reasoning, suggest_auto]
|
|
12460
|
+
properties:
|
|
12461
|
+
likelihood:
|
|
12462
|
+
type: number
|
|
12463
|
+
nullable: true
|
|
12464
|
+
description: Absent when there is no comparable history.
|
|
12465
|
+
reasoning: { type: string }
|
|
12466
|
+
suggest_auto:
|
|
12467
|
+
type: boolean
|
|
12468
|
+
description: Whether the operator's own policy already permits this.
|
|
12469
|
+
blocked_reason:
|
|
12470
|
+
type: string
|
|
12471
|
+
enum: [no_matching_rule, rule_requires_approval, above_configured_threshold, risk_tier_requires_step_up, action_is_sensitive]
|
|
12472
|
+
"403":
|
|
12473
|
+
$ref: "#/components/responses/Forbidden"
|
|
12474
|
+
"404":
|
|
12475
|
+
$ref: "#/components/responses/NotFound"
|
|
12476
|
+
|
|
12477
|
+
/v1/peers/by-connection/{connection_id}:
|
|
12478
|
+
get:
|
|
12479
|
+
tags: [Memory]
|
|
12480
|
+
summary: Resolve the peer for a platform connection
|
|
12481
|
+
operationId: getPeerByConnection
|
|
12482
|
+
parameters:
|
|
12483
|
+
- name: connection_id
|
|
12484
|
+
in: path
|
|
12485
|
+
required: true
|
|
12486
|
+
schema: { type: string, format: uuid }
|
|
12487
|
+
responses:
|
|
12488
|
+
"200":
|
|
12489
|
+
description: Peer
|
|
12490
|
+
content:
|
|
12491
|
+
application/json:
|
|
12492
|
+
schema:
|
|
12493
|
+
type: object
|
|
12494
|
+
properties:
|
|
12495
|
+
peer: { $ref: "#/components/schemas/Peer" }
|
|
12496
|
+
"403":
|
|
12497
|
+
$ref: "#/components/responses/Forbidden"
|
|
12498
|
+
"404":
|
|
12499
|
+
$ref: "#/components/responses/NotFound"
|
|
12500
|
+
|
|
12501
|
+
/v1/org/apply/diff:
|
|
12502
|
+
post:
|
|
12503
|
+
tags: [Organization]
|
|
12504
|
+
summary: What would this chart change?
|
|
12505
|
+
description: |
|
|
12506
|
+
Reconcile a chart against the org without changing anything. Human users
|
|
12507
|
+
only — a chart provisions agents, vaults and access policies, so an agent
|
|
12508
|
+
that could apply one could grant itself access to a vault it cannot
|
|
12509
|
+
currently read.
|
|
12510
|
+
|
|
12511
|
+
A POST rather than a GET because the chart is the request body, and a GET
|
|
12512
|
+
carrying a body is one many proxies and clients drop or mangle. Read-only
|
|
12513
|
+
either way.
|
|
12514
|
+
|
|
12515
|
+
The plan reports five outcomes per resource:
|
|
12516
|
+
|
|
12517
|
+
* `create` — not present, would be created.
|
|
12518
|
+
* `patch` — present, differs only in fields safe to change in place.
|
|
12519
|
+
* `unchanged` — present and matching.
|
|
12520
|
+
* `skipped_drifted` — **changed outside this chart**, so left alone.
|
|
12521
|
+
Someone edited it by hand for a reason; overwriting that because a file
|
|
12522
|
+
says otherwise is how a deployment tool destroys an incident fix.
|
|
12523
|
+
* `refused` — the chart asks for a change apply will not make. Guardrail
|
|
12524
|
+
fields are never patched here: editing them routes through the guardrail
|
|
12525
|
+
approval flow, and a reconciler writing them directly would be a way
|
|
12526
|
+
around it.
|
|
12527
|
+
|
|
12528
|
+
Pass `applied_state` from `.1claw/apply-state.json` so drift can be told
|
|
12529
|
+
from a first run — a pre-existing resource is not drifted, it was simply
|
|
12530
|
+
not created by this chart.
|
|
12531
|
+
operationId: diffChart
|
|
12532
|
+
requestBody:
|
|
12533
|
+
required: true
|
|
12534
|
+
content:
|
|
12535
|
+
application/json:
|
|
12536
|
+
schema:
|
|
12537
|
+
type: object
|
|
12538
|
+
required: [chart]
|
|
12539
|
+
properties:
|
|
12540
|
+
chart:
|
|
12541
|
+
type: object
|
|
12542
|
+
description: A chart document — `apiVersion`, `kind`, `metadata`, `spec`.
|
|
12543
|
+
applied_state:
|
|
12544
|
+
type: object
|
|
12545
|
+
additionalProperties: true
|
|
12546
|
+
description: What a previous apply recorded, keyed `kind/name`.
|
|
12547
|
+
responses:
|
|
12548
|
+
"200":
|
|
12549
|
+
description: The plan
|
|
12550
|
+
content:
|
|
12551
|
+
application/json:
|
|
12552
|
+
schema:
|
|
12553
|
+
type: object
|
|
12554
|
+
properties:
|
|
12555
|
+
chart_name: { type: string }
|
|
12556
|
+
actions:
|
|
12557
|
+
type: array
|
|
12558
|
+
items: { type: object }
|
|
12559
|
+
warnings:
|
|
12560
|
+
type: array
|
|
12561
|
+
items: { type: string }
|
|
12562
|
+
summary:
|
|
12563
|
+
type: object
|
|
12564
|
+
properties:
|
|
12565
|
+
create: { type: integer }
|
|
12566
|
+
patch: { type: integer }
|
|
12567
|
+
skipped_drifted: { type: integer }
|
|
12568
|
+
unchanged: { type: integer }
|
|
12569
|
+
refused: { type: integer }
|
|
12570
|
+
no_changes: { type: boolean }
|
|
12571
|
+
"400":
|
|
12572
|
+
$ref: "#/components/responses/BadRequest"
|
|
12573
|
+
"403":
|
|
12574
|
+
$ref: "#/components/responses/Forbidden"
|
|
12575
|
+
|
|
12576
|
+
/v1/notification-targets:
|
|
12577
|
+
get:
|
|
12578
|
+
tags: [Notifications]
|
|
12579
|
+
summary: List your notification targets
|
|
12580
|
+
operationId: listNotificationTargets
|
|
12581
|
+
responses:
|
|
12582
|
+
"200":
|
|
12583
|
+
description: Your targets
|
|
12584
|
+
content:
|
|
12585
|
+
application/json:
|
|
12586
|
+
schema:
|
|
12587
|
+
type: object
|
|
12588
|
+
properties:
|
|
12589
|
+
targets:
|
|
12590
|
+
type: array
|
|
12591
|
+
items:
|
|
12592
|
+
$ref: "#/components/schemas/NotificationTarget"
|
|
12593
|
+
post:
|
|
12594
|
+
tags: [Notifications]
|
|
12595
|
+
summary: Add a notification target
|
|
12596
|
+
description: |
|
|
12597
|
+
Where approvals and automation output reach a human: a phone number, an
|
|
12598
|
+
https webhook, an email address, or a push token.
|
|
12599
|
+
|
|
12600
|
+
An SMS target is created **unverified** and stays that way until someone
|
|
12601
|
+
proves they hold the number. Adding a number must not itself be an
|
|
12602
|
+
authorisation — otherwise a session borrowed for five minutes leaves
|
|
12603
|
+
behind a number that can approve things long after it is gone. An
|
|
12604
|
+
unverified target still receives notifications; it just cannot reply to
|
|
12605
|
+
decide one.
|
|
12606
|
+
operationId: createNotificationTarget
|
|
12607
|
+
requestBody:
|
|
12608
|
+
required: true
|
|
12609
|
+
content:
|
|
12610
|
+
application/json:
|
|
12611
|
+
schema:
|
|
12612
|
+
type: object
|
|
12613
|
+
required: [target_type, config]
|
|
12614
|
+
properties:
|
|
12615
|
+
target_type:
|
|
12616
|
+
type: string
|
|
12617
|
+
enum: [sms, webhook, expo, email]
|
|
12618
|
+
config:
|
|
12619
|
+
type: object
|
|
12620
|
+
description: |
|
|
12621
|
+
`{"phone_number": "+14155550123"}` for sms (E.164 only),
|
|
12622
|
+
`{"url": "https://…"}` for webhook (https only),
|
|
12623
|
+
`{"email": "…"}`, or `{"push_token": "…"}`.
|
|
12624
|
+
events:
|
|
12625
|
+
type: array
|
|
12626
|
+
items: { type: string }
|
|
12627
|
+
description: Empty means every event.
|
|
12628
|
+
agent_id:
|
|
12629
|
+
type: string
|
|
12630
|
+
format: uuid
|
|
12631
|
+
description: The agent whose SMS channel sends to this target.
|
|
12632
|
+
user_id:
|
|
12633
|
+
type: string
|
|
12634
|
+
format: uuid
|
|
12635
|
+
description: Defaults to the caller.
|
|
12636
|
+
responses:
|
|
12637
|
+
"201":
|
|
12638
|
+
description: Target created, unverified
|
|
12639
|
+
content:
|
|
12640
|
+
application/json:
|
|
12641
|
+
schema:
|
|
12642
|
+
$ref: "#/components/schemas/NotificationTarget"
|
|
12643
|
+
"400":
|
|
12644
|
+
$ref: "#/components/responses/BadRequest"
|
|
12645
|
+
"403":
|
|
12646
|
+
$ref: "#/components/responses/Forbidden"
|
|
12647
|
+
"409":
|
|
12648
|
+
$ref: "#/components/responses/Conflict"
|
|
12649
|
+
|
|
12650
|
+
/v1/notification-targets/{id}:
|
|
12651
|
+
delete:
|
|
12652
|
+
tags: [Notifications]
|
|
12653
|
+
summary: Remove a notification target
|
|
12654
|
+
operationId: deleteNotificationTarget
|
|
12655
|
+
parameters:
|
|
12656
|
+
- name: id
|
|
12657
|
+
in: path
|
|
12658
|
+
required: true
|
|
12659
|
+
schema: { type: string, format: uuid }
|
|
12660
|
+
responses:
|
|
12661
|
+
"204":
|
|
12662
|
+
description: Removed
|
|
12663
|
+
"403":
|
|
12664
|
+
$ref: "#/components/responses/Forbidden"
|
|
12665
|
+
"404":
|
|
12666
|
+
$ref: "#/components/responses/NotFound"
|
|
12667
|
+
|
|
12668
|
+
/v1/notification-targets/{id}/verify/start:
|
|
12669
|
+
post:
|
|
12670
|
+
tags: [Notifications]
|
|
12671
|
+
summary: Text a verification code to an SMS target
|
|
12672
|
+
description: |
|
|
12673
|
+
Sends a six-digit code from the same channel the target's notifications
|
|
12674
|
+
will come from — a code arriving from a different number than the one
|
|
12675
|
+
the recipient will later see is a code they are right to distrust.
|
|
12676
|
+
|
|
12677
|
+
Expires in 10 minutes. Five wrong answers void it.
|
|
12678
|
+
operationId: startNotificationTargetVerification
|
|
12679
|
+
parameters:
|
|
12680
|
+
- name: id
|
|
12681
|
+
in: path
|
|
12682
|
+
required: true
|
|
12683
|
+
schema: { type: string, format: uuid }
|
|
12684
|
+
responses:
|
|
12685
|
+
"200":
|
|
12686
|
+
description: Code sent
|
|
12687
|
+
content:
|
|
12688
|
+
application/json:
|
|
12689
|
+
schema:
|
|
12690
|
+
type: object
|
|
12691
|
+
properties:
|
|
12692
|
+
message: { type: string }
|
|
12693
|
+
expires_in_seconds: { type: integer }
|
|
12694
|
+
"400":
|
|
12695
|
+
$ref: "#/components/responses/BadRequest"
|
|
12696
|
+
"403":
|
|
12697
|
+
$ref: "#/components/responses/Forbidden"
|
|
12698
|
+
"404":
|
|
12699
|
+
$ref: "#/components/responses/NotFound"
|
|
12700
|
+
|
|
12701
|
+
/v1/notification-targets/{id}/verify:
|
|
12702
|
+
post:
|
|
12703
|
+
tags: [Notifications]
|
|
12704
|
+
summary: Submit the verification code
|
|
12705
|
+
operationId: completeNotificationTargetVerification
|
|
12706
|
+
parameters:
|
|
12707
|
+
- name: id
|
|
12708
|
+
in: path
|
|
12709
|
+
required: true
|
|
12710
|
+
schema: { type: string, format: uuid }
|
|
12711
|
+
requestBody:
|
|
12712
|
+
required: true
|
|
12713
|
+
content:
|
|
12714
|
+
application/json:
|
|
12715
|
+
schema:
|
|
12716
|
+
type: object
|
|
12717
|
+
required: [code]
|
|
12718
|
+
properties:
|
|
12719
|
+
code: { type: string, example: "042913" }
|
|
12720
|
+
responses:
|
|
12721
|
+
"200":
|
|
12722
|
+
description: Verified
|
|
12723
|
+
content:
|
|
12724
|
+
application/json:
|
|
12725
|
+
schema:
|
|
12726
|
+
type: object
|
|
12727
|
+
properties:
|
|
12728
|
+
verified: { type: boolean }
|
|
12729
|
+
"400":
|
|
12730
|
+
$ref: "#/components/responses/BadRequest"
|
|
12731
|
+
"403":
|
|
12732
|
+
$ref: "#/components/responses/Forbidden"
|
|
12733
|
+
"404":
|
|
12734
|
+
$ref: "#/components/responses/NotFound"
|
|
12735
|
+
|
|
12736
|
+
/v1/webhooks/sms/{webhook_path}:
|
|
12737
|
+
post:
|
|
12738
|
+
tags: [Channels]
|
|
12739
|
+
summary: Inbound SMS webhook (Twilio)
|
|
12740
|
+
description: |
|
|
12741
|
+
Called by Twilio when someone texts the channel's number. Public, because
|
|
12742
|
+
the provider calls it — so the `X-Twilio-Signature` header is the only
|
|
12743
|
+
thing establishing that a message is genuine, and it is verified over the
|
|
12744
|
+
exact public URL and every POST parameter.
|
|
12745
|
+
|
|
12746
|
+
A verified signature proves the message came from Twilio, **not** that it
|
|
12747
|
+
came from the right person: anyone who knows the number can text it and
|
|
12748
|
+
their message arrives correctly signed. So the sending number must also
|
|
12749
|
+
match a *verified* SMS notification target.
|
|
12750
|
+
|
|
12751
|
+
A reply may decide an approval only when its server-derived
|
|
12752
|
+
`risk_tier` is 1. Anything higher is answered with a link to confirm in
|
|
12753
|
+
the app; replying cannot decide it. When more than one approval is
|
|
12754
|
+
pending, a bare YES/NO is answered with a request for the reference code
|
|
12755
|
+
rather than applied to a guess.
|
|
12756
|
+
|
|
12757
|
+
Always answers 200 with TwiML — a non-2xx makes Twilio retry a message
|
|
12758
|
+
that was deliberately refused. The exception is a bad signature, which is
|
|
12759
|
+
403, because a persistently failing signature is a misconfiguration as
|
|
12760
|
+
often as an attack and silence would hide both.
|
|
12761
|
+
operationId: smsWebhook
|
|
12762
|
+
security: []
|
|
12763
|
+
parameters:
|
|
12764
|
+
- name: webhook_path
|
|
12765
|
+
in: path
|
|
12766
|
+
required: true
|
|
12767
|
+
schema: { type: string }
|
|
12768
|
+
- name: X-Twilio-Signature
|
|
12769
|
+
in: header
|
|
12770
|
+
required: true
|
|
12771
|
+
schema: { type: string }
|
|
12772
|
+
requestBody:
|
|
12773
|
+
required: true
|
|
12774
|
+
content:
|
|
12775
|
+
application/x-www-form-urlencoded:
|
|
12776
|
+
schema:
|
|
12777
|
+
type: object
|
|
12778
|
+
properties:
|
|
12779
|
+
From: { type: string, example: "+14155550123" }
|
|
12780
|
+
To: { type: string, example: "+14155550999" }
|
|
12781
|
+
Body: { type: string, example: "YES A1" }
|
|
12782
|
+
responses:
|
|
12783
|
+
"200":
|
|
12784
|
+
description: TwiML response; `<Response/>` when there is nothing to reply
|
|
12785
|
+
content:
|
|
12786
|
+
application/xml:
|
|
12787
|
+
schema: { type: string }
|
|
12788
|
+
"403":
|
|
12789
|
+
$ref: "#/components/responses/Forbidden"
|
|
12790
|
+
"404":
|
|
12791
|
+
$ref: "#/components/responses/NotFound"
|
|
12792
|
+
|
|
12793
|
+
/v1/webhooks/discord/{webhook_path}:
|
|
12794
|
+
post:
|
|
12795
|
+
tags: [Agent Channels]
|
|
12796
|
+
summary: Discord webhook
|
|
12797
|
+
description: Public webhook endpoint for receiving Discord bot interactions.
|
|
12798
|
+
operationId: discordWebhook
|
|
12799
|
+
security: []
|
|
12800
|
+
parameters:
|
|
12801
|
+
- name: webhook_path
|
|
12802
|
+
in: path
|
|
12803
|
+
required: true
|
|
12804
|
+
schema:
|
|
12805
|
+
type: string
|
|
12806
|
+
requestBody:
|
|
12807
|
+
required: true
|
|
12808
|
+
content:
|
|
12809
|
+
application/json:
|
|
12810
|
+
schema:
|
|
12811
|
+
type: object
|
|
12812
|
+
responses:
|
|
12813
|
+
"200":
|
|
12814
|
+
description: Webhook processed
|
|
12815
|
+
|
|
12816
|
+
# ---------------------------------------------------------------------------
|
|
12817
|
+
# OAuth Connect
|
|
12818
|
+
# ---------------------------------------------------------------------------
|
|
12819
|
+
|
|
12820
|
+
/v1/oauth/providers:
|
|
12821
|
+
get:
|
|
12822
|
+
tags: [OAuth Connect]
|
|
12823
|
+
summary: List OAuth providers
|
|
12824
|
+
description: |
|
|
12825
|
+
Returns the list of supported OAuth providers with their metadata,
|
|
12826
|
+
available scopes, and authorization URLs. No authentication required.
|
|
12827
|
+
operationId: listOAuthProviders
|
|
12828
|
+
security: []
|
|
12829
|
+
responses:
|
|
12830
|
+
"200":
|
|
12831
|
+
description: Provider list
|
|
12832
|
+
content:
|
|
12833
|
+
application/json:
|
|
12834
|
+
schema:
|
|
12835
|
+
$ref: "#/components/schemas/OAuthProviderListResponse"
|
|
12836
|
+
|
|
12837
|
+
/v1/connectors/presets:
|
|
12838
|
+
get:
|
|
12839
|
+
tags: [Connectors]
|
|
12840
|
+
summary: List connector presets
|
|
12841
|
+
description: |
|
|
12842
|
+
The catalogue of pre-built connectors — Gmail, Slack, GitHub and the rest.
|
|
12843
|
+
Each preset carries the OAuth provider and scopes to request, plus the
|
|
12844
|
+
binding config and host/path guardrails the agent will execute under.
|
|
12845
|
+
|
|
12846
|
+
No authentication required: this describes what 1Claw supports, not
|
|
12847
|
+
anything belonging to an organisation.
|
|
12848
|
+
operationId: listConnectorPresets
|
|
12849
|
+
security: []
|
|
12850
|
+
responses:
|
|
12851
|
+
"200":
|
|
12852
|
+
description: Preset catalogue
|
|
12853
|
+
content:
|
|
12854
|
+
application/json:
|
|
12855
|
+
schema:
|
|
12856
|
+
type: object
|
|
12857
|
+
properties:
|
|
12858
|
+
presets:
|
|
12859
|
+
type: array
|
|
12860
|
+
items:
|
|
12861
|
+
$ref: "#/components/schemas/ConnectorPreset"
|
|
12862
|
+
|
|
12863
|
+
/v1/agents/{agent_id}/connectors:
|
|
12864
|
+
get:
|
|
12865
|
+
tags: [Connectors]
|
|
12866
|
+
summary: List installed connectors
|
|
12867
|
+
description: |
|
|
12868
|
+
Connectors installed on this agent, and whether each one has actually
|
|
12869
|
+
been connected — an install creates the binding, but the binding is not
|
|
12870
|
+
usable until the OAuth round trip completes.
|
|
12871
|
+
operationId: listInstalledConnectors
|
|
12872
|
+
parameters:
|
|
12873
|
+
- name: agent_id
|
|
12874
|
+
in: path
|
|
12875
|
+
required: true
|
|
12876
|
+
schema: { type: string, format: uuid }
|
|
12877
|
+
responses:
|
|
12878
|
+
"200":
|
|
12879
|
+
description: Installed connectors
|
|
12880
|
+
content:
|
|
12881
|
+
application/json:
|
|
12882
|
+
schema:
|
|
12883
|
+
type: object
|
|
12884
|
+
properties:
|
|
12885
|
+
connectors:
|
|
12886
|
+
type: array
|
|
12887
|
+
items:
|
|
12888
|
+
$ref: "#/components/schemas/InstalledConnector"
|
|
12889
|
+
"403":
|
|
12890
|
+
$ref: "#/components/responses/Forbidden"
|
|
12891
|
+
"404":
|
|
12892
|
+
$ref: "#/components/responses/NotFound"
|
|
12893
|
+
|
|
12894
|
+
/v1/agents/{agent_id}/connectors/{slug}/install:
|
|
12895
|
+
post:
|
|
12896
|
+
tags: [Connectors]
|
|
12897
|
+
summary: Install a connector
|
|
12898
|
+
description: |
|
|
12899
|
+
Creates a binding from the preset — base URL, allowed hosts, allowed
|
|
12900
|
+
paths — and starts the OAuth flow for it. Send the user to the returned
|
|
12901
|
+
`authorization_url` to finish; until they do, the binding exists but
|
|
12902
|
+
holds no credential.
|
|
12903
|
+
|
|
12904
|
+
Human users only. Installing gives an agent reach into a third-party
|
|
12905
|
+
account, and the flow it starts is a person's browser.
|
|
12906
|
+
|
|
12907
|
+
Idempotent by binding name: re-installing re-runs the OAuth flow against
|
|
12908
|
+
the existing binding rather than creating a second one holding a second
|
|
12909
|
+
token for the same account. A name already taken by a binding that is
|
|
12910
|
+
not this connector returns 409.
|
|
12911
|
+
operationId: installConnector
|
|
12912
|
+
parameters:
|
|
12913
|
+
- name: agent_id
|
|
12914
|
+
in: path
|
|
12915
|
+
required: true
|
|
12916
|
+
schema: { type: string, format: uuid }
|
|
12917
|
+
- name: slug
|
|
12918
|
+
in: path
|
|
12919
|
+
required: true
|
|
12920
|
+
description: Connector preset slug, e.g. `gmail`.
|
|
12921
|
+
schema: { type: string }
|
|
12922
|
+
requestBody:
|
|
12923
|
+
required: true
|
|
12924
|
+
content:
|
|
12925
|
+
application/json:
|
|
12926
|
+
schema:
|
|
12927
|
+
type: object
|
|
12928
|
+
properties:
|
|
12929
|
+
binding_name:
|
|
12930
|
+
type: string
|
|
12931
|
+
description: Defaults to the preset slug.
|
|
12932
|
+
scopes:
|
|
12933
|
+
type: array
|
|
12934
|
+
items: { type: string }
|
|
12935
|
+
description: |
|
|
12936
|
+
Narrow the preset's scopes. Widening is refused — the
|
|
12937
|
+
preset's scope list is the reviewed part of a one-click
|
|
12938
|
+
install. Must still include the preset's required scopes.
|
|
12939
|
+
redirect_after:
|
|
12940
|
+
type: string
|
|
12941
|
+
description: Where to send the user after the OAuth round trip.
|
|
12942
|
+
responses:
|
|
12943
|
+
"201":
|
|
12944
|
+
description: Connector installed; OAuth may still be pending
|
|
12945
|
+
content:
|
|
12946
|
+
application/json:
|
|
12947
|
+
schema:
|
|
12948
|
+
type: object
|
|
12949
|
+
required: [binding_id, binding_name, preset_slug, next_step]
|
|
12950
|
+
properties:
|
|
12951
|
+
binding_id: { type: string, format: uuid }
|
|
12952
|
+
binding_name: { type: string }
|
|
12953
|
+
preset_slug: { type: string }
|
|
12954
|
+
authorization_url:
|
|
12955
|
+
type: string
|
|
12956
|
+
nullable: true
|
|
12957
|
+
description: Absent for connectors that use a pasted API key rather than OAuth.
|
|
12958
|
+
next_step:
|
|
12959
|
+
type: string
|
|
12960
|
+
description: What the user still has to do, in words.
|
|
12961
|
+
"400":
|
|
12962
|
+
$ref: "#/components/responses/BadRequest"
|
|
12963
|
+
"403":
|
|
12964
|
+
$ref: "#/components/responses/Forbidden"
|
|
12965
|
+
"404":
|
|
12966
|
+
$ref: "#/components/responses/NotFound"
|
|
12967
|
+
"409":
|
|
12968
|
+
$ref: "#/components/responses/Conflict"
|
|
11282
12969
|
|
|
11283
12970
|
/v1/agents/{agent_id}/oauth/connect:
|
|
11284
12971
|
post:
|
|
@@ -12656,30 +14343,6 @@ paths:
|
|
|
12656
14343
|
"404":
|
|
12657
14344
|
$ref: "#/components/responses/NotFound"
|
|
12658
14345
|
|
|
12659
|
-
/v1/auth/credential-recovery/requests/{id}:
|
|
12660
|
-
delete:
|
|
12661
|
-
tags: [Credential Recovery]
|
|
12662
|
-
summary: Cancel or reject a recovery request
|
|
12663
|
-
operationId: cancelCredentialRecovery
|
|
12664
|
-
security:
|
|
12665
|
-
- BearerAuth: []
|
|
12666
|
-
parameters:
|
|
12667
|
-
- name: id
|
|
12668
|
-
in: path
|
|
12669
|
-
required: true
|
|
12670
|
-
schema:
|
|
12671
|
-
type: string
|
|
12672
|
-
format: uuid
|
|
12673
|
-
responses:
|
|
12674
|
-
"204":
|
|
12675
|
-
description: Request cancelled
|
|
12676
|
-
"401":
|
|
12677
|
-
$ref: "#/components/responses/Unauthorized"
|
|
12678
|
-
"403":
|
|
12679
|
-
$ref: "#/components/responses/Forbidden"
|
|
12680
|
-
"404":
|
|
12681
|
-
$ref: "#/components/responses/NotFound"
|
|
12682
|
-
|
|
12683
14346
|
# ---------------------------------------------------------------------------
|
|
12684
14347
|
# Org Credential Recovery Policy
|
|
12685
14348
|
# ---------------------------------------------------------------------------
|
|
@@ -14241,6 +15904,67 @@ paths:
|
|
|
14241
15904
|
description: Not a human caller — agents and platform keys cannot pair a device
|
|
14242
15905
|
'409':
|
|
14243
15906
|
description: That label is already pinned to a different key
|
|
15907
|
+
get:
|
|
15908
|
+
tags: [Browser Bridge]
|
|
15909
|
+
summary: "List the browser bridges paired to this organization. Revoked devices are included: 'was this machine ever paired' is the question asked after a laptop goes missing."
|
|
15910
|
+
operationId: list_browser_devices
|
|
15911
|
+
responses:
|
|
15912
|
+
'200':
|
|
15913
|
+
description: The paired devices. No credential material is returned — the row holds an Argon2 hash and a prefix, and neither is exposed.
|
|
15914
|
+
content:
|
|
15915
|
+
application/json:
|
|
15916
|
+
schema:
|
|
15917
|
+
type: object
|
|
15918
|
+
properties:
|
|
15919
|
+
devices:
|
|
15920
|
+
type: array
|
|
15921
|
+
items:
|
|
15922
|
+
type: object
|
|
15923
|
+
properties:
|
|
15924
|
+
id:
|
|
15925
|
+
type: string
|
|
15926
|
+
format: uuid
|
|
15927
|
+
label:
|
|
15928
|
+
type: string
|
|
15929
|
+
platform:
|
|
15930
|
+
type: string
|
|
15931
|
+
nullable: true
|
|
15932
|
+
bridge_version:
|
|
15933
|
+
type: string
|
|
15934
|
+
nullable: true
|
|
15935
|
+
last_seen_at:
|
|
15936
|
+
type: string
|
|
15937
|
+
format: date-time
|
|
15938
|
+
nullable: true
|
|
15939
|
+
revoked_at:
|
|
15940
|
+
type: string
|
|
15941
|
+
format: date-time
|
|
15942
|
+
nullable: true
|
|
15943
|
+
description: Set once revoked. A revoked credential stops resolving.
|
|
15944
|
+
created_at:
|
|
15945
|
+
type: string
|
|
15946
|
+
format: date-time
|
|
15947
|
+
'401':
|
|
15948
|
+
description: Unauthenticated
|
|
15949
|
+
/v1/browser/devices/{id}:
|
|
15950
|
+
delete:
|
|
15951
|
+
tags: [Browser Bridge]
|
|
15952
|
+
summary: "Revoke a paired bridge. This is what makes a leaked bb_ credential stop working."
|
|
15953
|
+
operationId: revoke_browser_device
|
|
15954
|
+
parameters:
|
|
15955
|
+
- name: id
|
|
15956
|
+
in: path
|
|
15957
|
+
required: true
|
|
15958
|
+
schema:
|
|
15959
|
+
type: string
|
|
15960
|
+
format: uuid
|
|
15961
|
+
responses:
|
|
15962
|
+
'204':
|
|
15963
|
+
description: Revoked. Subsequent use of that credential resolves to nothing.
|
|
15964
|
+
'401':
|
|
15965
|
+
description: Unauthenticated
|
|
15966
|
+
'404':
|
|
15967
|
+
description: No such device in this organization
|
|
14244
15968
|
/v1/browser/credentials:
|
|
14245
15969
|
post:
|
|
14246
15970
|
tags: [Browser Bridge]
|
|
@@ -14271,7 +15995,7 @@ paths:
|
|
|
14271
15995
|
minItems: 1
|
|
14272
15996
|
items:
|
|
14273
15997
|
type: string
|
|
14274
|
-
description: "
|
|
15998
|
+
description: "Hostnames. A bare entry matches only itself; a leading dot ('.example.com') matches that host and any subdomain. URLs, ports and '*' are refused — '*' has no meaning to the matcher, so it would be stored and then match nothing."
|
|
14275
15999
|
sso_hosts:
|
|
14276
16000
|
type: array
|
|
14277
16001
|
items:
|
|
@@ -14407,7 +16131,13 @@ paths:
|
|
|
14407
16131
|
application/json:
|
|
14408
16132
|
schema:
|
|
14409
16133
|
type: object
|
|
14410
|
-
|
|
16134
|
+
# form_path, field_names, redirect_chain and current_generation are
|
|
16135
|
+
# required, not optional. They were accepted as absent and defaulted
|
|
16136
|
+
# server-side, which turned three of the policy's checks off: the
|
|
16137
|
+
# redirect loop never ran, current_generation was compared against
|
|
16138
|
+
# itself, and form_path defaulted to "", matching no fingerprint
|
|
16139
|
+
# pattern and denying every binding that carried one.
|
|
16140
|
+
required: [session_id, binding_id, tab_origin, frame_origin, frame_id, generation, form_path, field_names, redirect_chain, current_generation]
|
|
14411
16141
|
properties:
|
|
14412
16142
|
session_id:
|
|
14413
16143
|
type: string
|
|
@@ -14425,7 +16155,24 @@ paths:
|
|
|
14425
16155
|
description: "The bridge's navigation counter. Compared again at consume: a navigation in between means the page decided about is no longer the page in front of the bridge."
|
|
14426
16156
|
form_action_origin:
|
|
14427
16157
|
type: string
|
|
14428
|
-
description: "Where the form would POST. Checked as well as the two origins — a login form on an allowed page can still submit to somebody else's host."
|
|
16158
|
+
description: "Where the form would POST. Checked as well as the two origins — a login form on an allowed page can still submit to somebody else's host. Absent is not treated as 'same as the tab'; it denies."
|
|
16159
|
+
form_path:
|
|
16160
|
+
type: string
|
|
16161
|
+
description: Path of the form being filled, checked against the binding's fingerprint.
|
|
16162
|
+
field_names:
|
|
16163
|
+
type: array
|
|
16164
|
+
items:
|
|
16165
|
+
type: string
|
|
16166
|
+
description: "Field names on that form. Every field the fingerprint expects must be present; extra fields are fine, since sites add hidden inputs."
|
|
16167
|
+
redirect_chain:
|
|
16168
|
+
type: array
|
|
16169
|
+
items:
|
|
16170
|
+
type: string
|
|
16171
|
+
description: "Hosts the login has redirected through, in order. Each is checked against the binding's allowed hosts union its sso hosts."
|
|
16172
|
+
current_generation:
|
|
16173
|
+
type: integer
|
|
16174
|
+
format: int64
|
|
16175
|
+
description: The target's generation now. A mismatch with `generation` means the page moved and the fill is denied.
|
|
14429
16176
|
tab_origin:
|
|
14430
16177
|
type: string
|
|
14431
16178
|
description: "Origin of the tab being driven. Checked against the binding's allowed and sso hosts by exact host match."
|
|
@@ -15270,6 +17017,9 @@ components:
|
|
|
15270
17017
|
properties:
|
|
15271
17018
|
name:
|
|
15272
17019
|
type: string
|
|
17020
|
+
minLength: 1
|
|
17021
|
+
maxLength: 255
|
|
17022
|
+
description: Unique within the organization. Trimmed before it is stored, and the trimmed value is what must be unique. Counted in characters, not bytes.
|
|
15273
17023
|
description:
|
|
15274
17024
|
type: string
|
|
15275
17025
|
mpc_custody:
|
|
@@ -15869,6 +17619,22 @@ components:
|
|
|
15869
17619
|
additionalProperties: true
|
|
15870
17620
|
nullable: true
|
|
15871
17621
|
description: Graduated transaction approval policy (HITL thresholds). Separate from hard guardrails.
|
|
17622
|
+
action_approval_policy:
|
|
17623
|
+
type: object
|
|
17624
|
+
additionalProperties: true
|
|
17625
|
+
nullable: true
|
|
17626
|
+
description: |
|
|
17627
|
+
Which business actions this agent must ask a human about, and above what
|
|
17628
|
+
amount. `{}` means no per-action rules.
|
|
17629
|
+
|
|
17630
|
+
Shape: `{ "default_mode": "deny|approve|allow", "rules": [ { "action_type":
|
|
17631
|
+
"refund.create", "mode": "approve", "require_for_amount_above_usd": "50",
|
|
17632
|
+
"summary_template": "Refund {{amount_usd}} to {{customer_email}}" } ] }`.
|
|
17633
|
+
|
|
17634
|
+
A rule can only raise the bar. Editing this is classified as a guardrail
|
|
17635
|
+
widening, so it routes through the same approval flow as loosening a
|
|
17636
|
+
transaction limit. Malformed rules are rejected on write rather than
|
|
17637
|
+
ignored at request time.
|
|
15872
17638
|
typed_data_policy:
|
|
15873
17639
|
type: string
|
|
15874
17640
|
enum: [deny, approve]
|
|
@@ -16051,6 +17817,22 @@ components:
|
|
|
16051
17817
|
additionalProperties: true
|
|
16052
17818
|
nullable: true
|
|
16053
17819
|
description: Graduated transaction approval policy (HITL thresholds).
|
|
17820
|
+
action_approval_policy:
|
|
17821
|
+
type: object
|
|
17822
|
+
additionalProperties: true
|
|
17823
|
+
nullable: true
|
|
17824
|
+
description: |
|
|
17825
|
+
Which business actions this agent must ask a human about, and above what
|
|
17826
|
+
amount. `{}` means no per-action rules.
|
|
17827
|
+
|
|
17828
|
+
Shape: `{ "default_mode": "deny|approve|allow", "rules": [ { "action_type":
|
|
17829
|
+
"refund.create", "mode": "approve", "require_for_amount_above_usd": "50",
|
|
17830
|
+
"summary_template": "Refund {{amount_usd}} to {{customer_email}}" } ] }`.
|
|
17831
|
+
|
|
17832
|
+
A rule can only raise the bar. Editing this is classified as a guardrail
|
|
17833
|
+
widening, so it routes through the same approval flow as loosening a
|
|
17834
|
+
transaction limit. Malformed rules are rejected on write rather than
|
|
17835
|
+
ignored at request time.
|
|
16054
17836
|
typed_data_policy:
|
|
16055
17837
|
type: string
|
|
16056
17838
|
enum: [deny, approve]
|
|
@@ -16322,6 +18104,22 @@ components:
|
|
|
16322
18104
|
additionalProperties: true
|
|
16323
18105
|
nullable: true
|
|
16324
18106
|
description: Graduated transaction approval policy (HITL thresholds).
|
|
18107
|
+
action_approval_policy:
|
|
18108
|
+
type: object
|
|
18109
|
+
additionalProperties: true
|
|
18110
|
+
nullable: true
|
|
18111
|
+
description: |
|
|
18112
|
+
Which business actions this agent must ask a human about, and above what
|
|
18113
|
+
amount. `{}` means no per-action rules.
|
|
18114
|
+
|
|
18115
|
+
Shape: `{ "default_mode": "deny|approve|allow", "rules": [ { "action_type":
|
|
18116
|
+
"refund.create", "mode": "approve", "require_for_amount_above_usd": "50",
|
|
18117
|
+
"summary_template": "Refund {{amount_usd}} to {{customer_email}}" } ] }`.
|
|
18118
|
+
|
|
18119
|
+
A rule can only raise the bar. Editing this is classified as a guardrail
|
|
18120
|
+
widening, so it routes through the same approval flow as loosening a
|
|
18121
|
+
transaction limit. Malformed rules are rejected on write rather than
|
|
18122
|
+
ignored at request time.
|
|
16325
18123
|
typed_data_policy:
|
|
16326
18124
|
type: string
|
|
16327
18125
|
enum: [deny, approve]
|
|
@@ -19797,6 +21595,140 @@ components:
|
|
|
19797
21595
|
type: string
|
|
19798
21596
|
format: date-time
|
|
19799
21597
|
|
|
21598
|
+
FleetSummaryResponse:
|
|
21599
|
+
type: object
|
|
21600
|
+
properties:
|
|
21601
|
+
template_id:
|
|
21602
|
+
type: string
|
|
21603
|
+
format: uuid
|
|
21604
|
+
template_name:
|
|
21605
|
+
type: string
|
|
21606
|
+
current_version:
|
|
21607
|
+
type: integer
|
|
21608
|
+
spec_hash:
|
|
21609
|
+
type: [string, "null"]
|
|
21610
|
+
description: >
|
|
21611
|
+
SHA-256 of the template spec. Lets a caller tell a version bump that
|
|
21612
|
+
changed nothing from one that did. Null on templates written before
|
|
21613
|
+
migration 245.
|
|
21614
|
+
total_agents:
|
|
21615
|
+
type: integer
|
|
21616
|
+
format: int64
|
|
21617
|
+
version_skew:
|
|
21618
|
+
type: array
|
|
21619
|
+
description: How the cohort splits across the versions it was provisioned from.
|
|
21620
|
+
items:
|
|
21621
|
+
type: object
|
|
21622
|
+
properties:
|
|
21623
|
+
template_version:
|
|
21624
|
+
type: [integer, "null"]
|
|
21625
|
+
agents:
|
|
21626
|
+
type: integer
|
|
21627
|
+
format: int64
|
|
21628
|
+
agents_on_current_version:
|
|
21629
|
+
type: integer
|
|
21630
|
+
format: int64
|
|
21631
|
+
agents_behind:
|
|
21632
|
+
type: integer
|
|
21633
|
+
format: int64
|
|
21634
|
+
drifted_agents:
|
|
21635
|
+
type: integer
|
|
21636
|
+
format: int64
|
|
21637
|
+
description: Agents a previous rollout declined to touch.
|
|
21638
|
+
bulk_patchable_fields:
|
|
21639
|
+
type: array
|
|
21640
|
+
description: >
|
|
21641
|
+
The fields bulk-patch and rollout will carry. Read this rather than
|
|
21642
|
+
hard-coding the list; it is deliberately narrower than a single-agent
|
|
21643
|
+
PATCH and may narrow further.
|
|
21644
|
+
items:
|
|
21645
|
+
type: string
|
|
21646
|
+
|
|
21647
|
+
ListFleetAgentsResponse:
|
|
21648
|
+
type: object
|
|
21649
|
+
properties:
|
|
21650
|
+
agents:
|
|
21651
|
+
type: array
|
|
21652
|
+
items:
|
|
21653
|
+
$ref: "#/components/schemas/FleetAgent"
|
|
21654
|
+
limit:
|
|
21655
|
+
type: integer
|
|
21656
|
+
offset:
|
|
21657
|
+
type: integer
|
|
21658
|
+
current_version:
|
|
21659
|
+
type: integer
|
|
21660
|
+
|
|
21661
|
+
FleetAgent:
|
|
21662
|
+
type: object
|
|
21663
|
+
properties:
|
|
21664
|
+
agent_id:
|
|
21665
|
+
type: string
|
|
21666
|
+
format: uuid
|
|
21667
|
+
name:
|
|
21668
|
+
type: string
|
|
21669
|
+
org_id:
|
|
21670
|
+
type: string
|
|
21671
|
+
format: uuid
|
|
21672
|
+
platform_connection_id:
|
|
21673
|
+
type: [string, "null"]
|
|
21674
|
+
format: uuid
|
|
21675
|
+
provisioned_from_version:
|
|
21676
|
+
type: [integer, "null"]
|
|
21677
|
+
last_fleet_sync_at:
|
|
21678
|
+
type: [string, "null"]
|
|
21679
|
+
format: date-time
|
|
21680
|
+
drift_fields:
|
|
21681
|
+
type: array
|
|
21682
|
+
description: >
|
|
21683
|
+
Fields a rollout skipped because they were changed outside fleet
|
|
21684
|
+
control. The standing answer to "why is this agent behind?".
|
|
21685
|
+
items:
|
|
21686
|
+
type: string
|
|
21687
|
+
is_active:
|
|
21688
|
+
type: boolean
|
|
21689
|
+
is_current:
|
|
21690
|
+
type: boolean
|
|
21691
|
+
|
|
21692
|
+
FleetRolloutResponse:
|
|
21693
|
+
type: object
|
|
21694
|
+
properties:
|
|
21695
|
+
job_id:
|
|
21696
|
+
type: [string, "null"]
|
|
21697
|
+
format: uuid
|
|
21698
|
+
description: Null for a dry run, which claims no job.
|
|
21699
|
+
to_version:
|
|
21700
|
+
type: integer
|
|
21701
|
+
dry_run:
|
|
21702
|
+
type: boolean
|
|
21703
|
+
forced:
|
|
21704
|
+
type: boolean
|
|
21705
|
+
total_agents:
|
|
21706
|
+
type: integer
|
|
21707
|
+
format: int64
|
|
21708
|
+
synced:
|
|
21709
|
+
type: integer
|
|
21710
|
+
already_current:
|
|
21711
|
+
type: integer
|
|
21712
|
+
skipped_drifted:
|
|
21713
|
+
type: integer
|
|
21714
|
+
outcomes:
|
|
21715
|
+
type: array
|
|
21716
|
+
items:
|
|
21717
|
+
type: object
|
|
21718
|
+
properties:
|
|
21719
|
+
outcome:
|
|
21720
|
+
type: string
|
|
21721
|
+
enum: [already_current, synced, skipped_drifted]
|
|
21722
|
+
agent_id:
|
|
21723
|
+
type: string
|
|
21724
|
+
format: uuid
|
|
21725
|
+
fields:
|
|
21726
|
+
type: array
|
|
21727
|
+
items: { type: string }
|
|
21728
|
+
drift_fields:
|
|
21729
|
+
type: array
|
|
21730
|
+
items: { type: string }
|
|
21731
|
+
|
|
19800
21732
|
UpsertPlatformUserRequest:
|
|
19801
21733
|
type: object
|
|
19802
21734
|
properties:
|
|
@@ -20359,6 +22291,170 @@ components:
|
|
|
20359
22291
|
type: string
|
|
20360
22292
|
description: Optional human-readable reason for the decision
|
|
20361
22293
|
|
|
22294
|
+
UsageCounts:
|
|
22295
|
+
type: object
|
|
22296
|
+
required: [api_requests, signatures, execution_intents, execution_intents_tee, inference_usd, credits_debited_cents]
|
|
22297
|
+
properties:
|
|
22298
|
+
api_requests: { type: integer, format: int64 }
|
|
22299
|
+
signatures: { type: integer, format: int64 }
|
|
22300
|
+
execution_intents: { type: integer, format: int64 }
|
|
22301
|
+
execution_intents_tee: { type: integer, format: int64 }
|
|
22302
|
+
inference_usd:
|
|
22303
|
+
type: string
|
|
22304
|
+
description: A decimal string. Money is not a float; zero is "0".
|
|
22305
|
+
example: "3.42"
|
|
22306
|
+
credits_debited_cents: { type: integer, format: int64 }
|
|
22307
|
+
|
|
22308
|
+
AppUsageReport:
|
|
22309
|
+
type: object
|
|
22310
|
+
required: [app_id, period_start, period_end, connections, unattributed, totals, has_ambiguous_usage]
|
|
22311
|
+
properties:
|
|
22312
|
+
app_id: { type: string, format: uuid }
|
|
22313
|
+
period_start: { type: string, format: date-time }
|
|
22314
|
+
period_end:
|
|
22315
|
+
type: string
|
|
22316
|
+
format: date-time
|
|
22317
|
+
description: Exclusive. The period is half-open, so an event at midnight belongs to one month, not two.
|
|
22318
|
+
connections:
|
|
22319
|
+
type: array
|
|
22320
|
+
items:
|
|
22321
|
+
type: object
|
|
22322
|
+
required: [connection_id, usage]
|
|
22323
|
+
properties:
|
|
22324
|
+
connection_id: { type: string, format: uuid }
|
|
22325
|
+
usage: { $ref: "#/components/schemas/UsageCounts" }
|
|
22326
|
+
unattributed:
|
|
22327
|
+
type: object
|
|
22328
|
+
description: Usage that could not be charged to a connection.
|
|
22329
|
+
properties:
|
|
22330
|
+
ambiguous:
|
|
22331
|
+
allOf:
|
|
22332
|
+
- $ref: "#/components/schemas/UsageCounts"
|
|
22333
|
+
description: The agent belongs to several connections and none was named. This belongs to someone.
|
|
22334
|
+
none:
|
|
22335
|
+
allOf:
|
|
22336
|
+
- $ref: "#/components/schemas/UsageCounts"
|
|
22337
|
+
description: No platform linkage. Normal for most traffic.
|
|
22338
|
+
totals:
|
|
22339
|
+
allOf:
|
|
22340
|
+
- $ref: "#/components/schemas/UsageCounts"
|
|
22341
|
+
description: Connections plus both unattributed buckets. Derived, not queried.
|
|
22342
|
+
has_ambiguous_usage:
|
|
22343
|
+
type: boolean
|
|
22344
|
+
description: Some usage this period belongs to an end-user who cannot be identified.
|
|
22345
|
+
|
|
22346
|
+
Peer:
|
|
22347
|
+
type: object
|
|
22348
|
+
required: [id, peer_type, peer_ref, profile, status, observer_count, created_at]
|
|
22349
|
+
properties:
|
|
22350
|
+
id: { type: string, format: uuid }
|
|
22351
|
+
peer_type: { type: string, enum: [user, platform_connection, external] }
|
|
22352
|
+
peer_ref: { type: string }
|
|
22353
|
+
display_name: { type: string, nullable: true }
|
|
22354
|
+
profile: { type: object, additionalProperties: true }
|
|
22355
|
+
status:
|
|
22356
|
+
type: string
|
|
22357
|
+
enum: [active, archived]
|
|
22358
|
+
description: |
|
|
22359
|
+
Archived when a connection is disconnected. Agents lose observation;
|
|
22360
|
+
the person keeps export and delete.
|
|
22361
|
+
observer_count:
|
|
22362
|
+
type: integer
|
|
22363
|
+
description: How many agents observe this peer. The list itself is not returned here.
|
|
22364
|
+
created_at: { type: string, format: date-time }
|
|
22365
|
+
|
|
22366
|
+
PeerFact:
|
|
22367
|
+
type: object
|
|
22368
|
+
required: [fact_key, fact_value, provenance, edited_by_human, updated_at]
|
|
22369
|
+
properties:
|
|
22370
|
+
fact_key: { type: string, example: "approval_tendency:refund.create|0-10|known|a@b.co" }
|
|
22371
|
+
fact_value: { type: object, additionalProperties: true }
|
|
22372
|
+
confidence:
|
|
22373
|
+
type: string
|
|
22374
|
+
nullable: true
|
|
22375
|
+
description: 0..1, capped below certainty — no history makes the next decision certain.
|
|
22376
|
+
provenance:
|
|
22377
|
+
type: array
|
|
22378
|
+
items: { type: object }
|
|
22379
|
+
description: |
|
|
22380
|
+
Why this is believed. Entries are `event`, `tombstone` (the event has
|
|
22381
|
+
expired; kind and decision are kept, content is not) or `human`.
|
|
22382
|
+
edited_by_human:
|
|
22383
|
+
type: boolean
|
|
22384
|
+
description: A person corrected this. The processor will not overwrite it.
|
|
22385
|
+
updated_at: { type: string, format: date-time }
|
|
22386
|
+
|
|
22387
|
+
NotificationTarget:
|
|
22388
|
+
type: object
|
|
22389
|
+
required: [id, target_type, config, events, is_active, verified, created_at]
|
|
22390
|
+
properties:
|
|
22391
|
+
id: { type: string, format: uuid }
|
|
22392
|
+
target_type:
|
|
22393
|
+
type: string
|
|
22394
|
+
enum: [sms, webhook, expo, email]
|
|
22395
|
+
user_id: { type: string, format: uuid, nullable: true }
|
|
22396
|
+
agent_id: { type: string, format: uuid, nullable: true }
|
|
22397
|
+
config: { type: object, additionalProperties: true }
|
|
22398
|
+
events:
|
|
22399
|
+
type: array
|
|
22400
|
+
items: { type: string }
|
|
22401
|
+
is_active: { type: boolean }
|
|
22402
|
+
verified:
|
|
22403
|
+
type: boolean
|
|
22404
|
+
description: |
|
|
22405
|
+
An unverified SMS target receives notifications but cannot decide
|
|
22406
|
+
an approval by reply.
|
|
22407
|
+
created_at: { type: string, format: date-time }
|
|
22408
|
+
|
|
22409
|
+
ConnectorPreset:
|
|
22410
|
+
type: object
|
|
22411
|
+
required: [slug, display_name, description, category, binding_type, base_url, requires_oauth]
|
|
22412
|
+
properties:
|
|
22413
|
+
slug: { type: string, example: gmail }
|
|
22414
|
+
display_name: { type: string, example: Gmail }
|
|
22415
|
+
description: { type: string }
|
|
22416
|
+
category: { type: string, example: communication }
|
|
22417
|
+
provider_slug:
|
|
22418
|
+
type: string
|
|
22419
|
+
nullable: true
|
|
22420
|
+
description: "`oauth_providers.slug`, or null when the connector uses a pasted API key."
|
|
22421
|
+
oauth_scopes:
|
|
22422
|
+
type: array
|
|
22423
|
+
items: { type: string }
|
|
22424
|
+
required_scopes:
|
|
22425
|
+
type: array
|
|
22426
|
+
items: { type: string }
|
|
22427
|
+
description: Scopes without which the connector cannot do anything.
|
|
22428
|
+
binding_type: { type: string, example: http }
|
|
22429
|
+
base_url: { type: string, format: uri }
|
|
22430
|
+
allowed_hosts:
|
|
22431
|
+
type: array
|
|
22432
|
+
items: { type: string }
|
|
22433
|
+
description: Hosts the installed binding may reach. Always includes the base URL's host.
|
|
22434
|
+
documentation_url: { type: string, format: uri }
|
|
22435
|
+
tier_required: { type: string, example: free }
|
|
22436
|
+
requires_oauth: { type: boolean }
|
|
22437
|
+
|
|
22438
|
+
InstalledConnector:
|
|
22439
|
+
type: object
|
|
22440
|
+
required: [binding_id, binding_name, preset_slug, is_active, connected, needs_reauth, created_at]
|
|
22441
|
+
properties:
|
|
22442
|
+
binding_id: { type: string, format: uuid }
|
|
22443
|
+
binding_name: { type: string }
|
|
22444
|
+
preset_slug: { type: string }
|
|
22445
|
+
display_name:
|
|
22446
|
+
type: string
|
|
22447
|
+
nullable: true
|
|
22448
|
+
description: Null if the preset has since been retired from the catalogue.
|
|
22449
|
+
is_active: { type: boolean }
|
|
22450
|
+
connected:
|
|
22451
|
+
type: boolean
|
|
22452
|
+
description: The OAuth round trip completed and a token is stored.
|
|
22453
|
+
needs_reauth:
|
|
22454
|
+
type: boolean
|
|
22455
|
+
description: The stored token was rejected; the user must reconnect.
|
|
22456
|
+
created_at: { type: string, format: date-time }
|
|
22457
|
+
|
|
20362
22458
|
ApprovalResponse:
|
|
20363
22459
|
type: object
|
|
20364
22460
|
required: [id, org_id, user_id, action, target_type, target_id, risk_tier, status, summary, created_at]
|
|
@@ -20386,6 +22482,23 @@ components:
|
|
|
20386
22482
|
type: integer
|
|
20387
22483
|
minimum: 1
|
|
20388
22484
|
maximum: 3
|
|
22485
|
+
description: "The tier actually enforced. Authoritative."
|
|
22486
|
+
declared_risk_tier:
|
|
22487
|
+
type: integer
|
|
22488
|
+
minimum: 1
|
|
22489
|
+
maximum: 3
|
|
22490
|
+
nullable: true
|
|
22491
|
+
description: "What the caller asked for, when it asked for anything."
|
|
22492
|
+
declared_below_floor:
|
|
22493
|
+
type: boolean
|
|
22494
|
+
description: "The caller asked for a lower tier than policy required."
|
|
22495
|
+
human_summary:
|
|
22496
|
+
type: string
|
|
22497
|
+
nullable: true
|
|
22498
|
+
description: "Plain-language line sent to SMS, push and email."
|
|
22499
|
+
payload:
|
|
22500
|
+
type: object
|
|
22501
|
+
description: "What the action will do, as submitted."
|
|
20389
22502
|
status:
|
|
20390
22503
|
type: string
|
|
20391
22504
|
enum: [pending, approved, rejected, expired]
|
|
@@ -20740,7 +22853,7 @@ components:
|
|
|
20740
22853
|
|
|
20741
22854
|
ConnectionUsageResponse:
|
|
20742
22855
|
type: object
|
|
20743
|
-
required: [connection_id, period, inference_spent_usd]
|
|
22856
|
+
required: [connection_id, period, inference_spent_usd, usage, period_start, period_end]
|
|
20744
22857
|
properties:
|
|
20745
22858
|
connection_id:
|
|
20746
22859
|
type: string
|
|
@@ -20750,6 +22863,23 @@ components:
|
|
|
20750
22863
|
description: UTC month (YYYY-MM)
|
|
20751
22864
|
inference_spent_usd:
|
|
20752
22865
|
type: string
|
|
22866
|
+
description: |
|
|
22867
|
+
Kept for compatibility — this field predates the breakdown below and
|
|
22868
|
+
existing integrations read it. Same number as `usage.inference_usd`.
|
|
22869
|
+
usage:
|
|
22870
|
+
allOf:
|
|
22871
|
+
- $ref: "#/components/schemas/UsageCounts"
|
|
22872
|
+
description: |
|
|
22873
|
+
Everything billable for this connection in the period. Derived from the
|
|
22874
|
+
same grouped query as the app report, so a connection can never report a
|
|
22875
|
+
number the app report disagrees with.
|
|
22876
|
+
period_start:
|
|
22877
|
+
type: string
|
|
22878
|
+
format: date-time
|
|
22879
|
+
period_end:
|
|
22880
|
+
type: string
|
|
22881
|
+
format: date-time
|
|
22882
|
+
description: Exclusive. The period is half-open.
|
|
20753
22883
|
|
|
20754
22884
|
EntitlementsListResponse:
|
|
20755
22885
|
type: object
|