diff --git a/packages/store/scripts/api-schema/schema.json b/packages/store/scripts/api-schema/schema.json index c87e9026418..f19d8faf185 100644 --- a/packages/store/scripts/api-schema/schema.json +++ b/packages/store/scripts/api-schema/schema.json @@ -498,6 +498,9 @@ } } } + }, + "403": { + "description": "Not an admin" } }, "summary": "Get the billing portal session URL for a space", @@ -584,6 +587,12 @@ } } } + }, + "403": { + "description": "Not an admin, or a payment link this workspace is not offered" + }, + "409": { + "description": "This plan doesn't offer enough Safe seats for the workspace's current Safes" } }, "summary": "Create a checkout session for a payment link", @@ -592,6 +601,137 @@ ] } }, + "/v1/billing/spaces/{spaceId}/subscriptions/{subscriptionId}/preview-update": { + "get": { + "operationId": "billingPreviewSubscriptionUpdateV1", + "parameters": [ + { + "name": "subscriptionId", + "required": true, + "in": "path", + "description": "Subscription identifier", + "schema": { + "type": "string" + } + }, + { + "name": "planId", + "required": true, + "in": "query", + "description": "The price id of the plan to preview", + "schema": { + "type": "string" + } + }, + { + "name": "spaceId", + "required": true, + "in": "path", + "description": "Space UUID", + "schema": { + "example": "123e4567-e89b-12d3-a456-426614174000", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscriptionUpdatePreview" + } + } + } + }, + "403": { + "description": "Not an admin, or a plan this workspace is not offered" + }, + "404": { + "description": "Subscription not found" + }, + "409": { + "description": "Already on this plan" + }, + "422": { + "description": "Malformed subscriptionId or planId" + } + }, + "summary": "Preview what moving a subscription to another plan would cost", + "tags": [ + "billing" + ] + } + }, + "/v1/billing/spaces/{spaceId}/subscriptions/{subscriptionId}": { + "patch": { + "description": "Safes in `removedSafes` are removed from the workspace first, then the plan changes. If the plan change fails after that, the answer is 502 and sending the same request again finishes it.", + "operationId": "billingUpdateSubscriptionV1", + "parameters": [ + { + "name": "subscriptionId", + "required": true, + "in": "path", + "description": "Subscription identifier", + "schema": { + "type": "string" + } + }, + { + "name": "spaceId", + "required": true, + "in": "path", + "description": "Space UUID", + "schema": { + "example": "123e4567-e89b-12d3-a456-426614174000", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSubscriptionDto" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSubscriptionResult" + } + } + } + }, + "403": { + "description": "Not an admin, a plan this workspace is not offered, or a named paymentLinkId this workspace is not offered" + }, + "404": { + "description": "Subscription not found" + }, + "409": { + "description": "One of:\n- Already on this plan\n- The subscription is not in an updatable state\n- Several offered links sell the plan and none was named\n- The target plan doesn't offer enough Safe seats for the workspace's current Safes" + }, + "422": { + "description": "The named payment link does not offer this plan" + }, + "502": { + "description": "The billing service reported the plan change as unsuccessful, or failed after `removedSafes` were removed" + } + }, + "summary": "Move a subscription onto another plan", + "tags": [ + "billing" + ] + } + }, "/v1/billing/sessions/{sessionId}": { "get": { "operationId": "billingGetCheckoutSessionV1", @@ -1853,6 +1993,9 @@ }, "404": { "description": "Message not found" + }, + "422": { + "description": "Invalid chainId or messageHash" } }, "summary": "Get message by hash", @@ -1908,6 +2051,9 @@ }, "404": { "description": "Safe not found on the specified chain" + }, + "422": { + "description": "Invalid chainId or safeAddress" } }, "summary": "Get messages for Safe", @@ -1956,6 +2102,9 @@ }, "400": { "description": "Invalid message format or signature" + }, + "422": { + "description": "Invalid chainId, safeAddress or request body" } }, "summary": "Create message", @@ -2009,6 +2158,9 @@ }, "404": { "description": "Message not found" + }, + "422": { + "description": "Invalid chainId, messageHash or request body" } }, "summary": "Add message signature", @@ -2058,6 +2210,9 @@ }, "404": { "description": "User not found - the authenticated wallet is not associated with any user" + }, + "409": { + "description": "User is the last admin of at least one workspace - promote another admin or delete the workspace first" } }, "summary": "Delete user", @@ -2175,7 +2330,7 @@ }, "/v1/spaces/{spaceId}/address-book": { "get": { - "description": "Retrieves all address book entries for a specific space. Address books help organize and label frequently used addresses.", + "description": "Retrieves all address book entries for a specific space, with the tags of each entry and every tag of the space. Address books help organize and label frequently used addresses.", "operationId": "addressBooksGetAddressBookItemsV1", "parameters": [ { @@ -2207,10 +2362,10 @@ "description": "Authentication required - valid JWT token must be provided" }, "403": { - "description": "Access forbidden - user is not a member of this space" + "description": "Access forbidden - user is not an active member of this space" }, "404": { - "description": "User, member, or space not found" + "description": "Space not found" } }, "summary": "Get space address book", @@ -2219,7 +2374,7 @@ ] }, "put": { - "description": "Creates or updates address book entries for a space. This allows adding labels and organizing frequently used addresses.", + "description": "Creates or updates address book entries for a space. This allows adding labels and organizing frequently used addresses. An entry that carries tags gets exactly those tags; an entry without tags keeps its current tags.", "operationId": "addressBooksUpsertAddressBookItemsV1", "parameters": [ { @@ -2256,16 +2411,19 @@ } }, "400": { - "description": "Address book items limit exceeded or invalid data provided" + "description": "Invalid space identifier, address book items limit exceeded, or space tag limit reached" }, "401": { "description": "Authentication required - valid JWT token must be provided" }, "403": { - "description": "Access forbidden - user is not authorized to modify this address book" + "description": "Access forbidden - user is not an active admin of this space" }, "404": { - "description": "User, member, or space not found" + "description": "Space not found" + }, + "422": { + "description": "Invalid body - an invalid address, name or chain ID, an invalid tag name, or more tags on an entry than allowed" } }, "summary": "Update space address book", @@ -2274,10 +2432,10 @@ ] } }, - "/v1/spaces/{spaceId}/address-book/{address}": { - "delete": { - "description": "Removes a specific address from the space address book by its address.", - "operationId": "addressBooksDeleteByAddressV1", + "/v1/spaces/{spaceId}/address-book/tags": { + "put": { + "description": "Replaces the tags of one or more address book entries. Any active member of the space may set tags. A tag name the space does not have yet creates the tag. The request is all or nothing: if one entry cannot be tagged, no entry changes.", + "operationId": "addressBooksSetContactTagsV1", "parameters": [ { "name": "spaceId", @@ -2288,155 +2446,403 @@ "example": "123e4567-e89b-12d3-a456-426614174000", "type": "string" } - }, - { - "name": "address", - "required": true, - "in": "path", - "description": "Address to remove from the address book (0x prefixed hex string)", - "schema": { - "type": "string" - } } ], + "requestBody": { + "required": true, + "description": "The entries to tag, each with its full set of tag names", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetContactTagsDto" + } + } + } + }, "responses": { - "204": { - "description": "Address book entry deleted successfully" + "200": { + "description": "Tags set successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SpaceAddressBookDto" + } + } + } }, "400": { - "description": "Invalid space identifier" + "description": "Invalid space identifier, the space tag limit is reached, or more entries than the address book can hold" + }, + "401": { + "description": "Authentication required - valid JWT token must be provided" }, "403": { - "description": "Access forbidden - user is not authorized to modify this address book" + "description": "Access forbidden - user is not an active member of this space" }, "404": { - "description": "User, member, space, or address book entry not found" + "description": "Space not found, or an address is not in the address book" + }, + "422": { + "description": "Invalid body - no entries, an address listed twice, an invalid address or tag name, or more tags on an entry than allowed" + }, + "429": { + "description": "Rate limit exceeded" } }, - "summary": "Delete address book entry", + "summary": "Set address book entry tags", "tags": [ "spaces" ] - } - }, - "/v1/spaces/{spaceId}/address-book/requests": { - "get": { - "description": "Retrieves pending requests to add contacts to the space address book. Admins see all pending requests, members see only their own.", - "operationId": "addressBookRequestsGetPendingRequestsV1", + }, + "post": { + "description": "Creates a tag of the space with no contacts, in a random unused colour. Any active member of the space may create tags.", + "operationId": "addressBooksCreateTagV1", "parameters": [ { "name": "spaceId", "required": true, "in": "path", - "description": "Space UUID", + "description": "Space UUID containing the address book", "schema": { "example": "123e4567-e89b-12d3-a456-426614174000", "type": "string" } } ], + "requestBody": { + "required": true, + "description": "The tag name", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateTagDto" + } + } + } + }, "responses": { - "200": { - "description": "Pending requests retrieved successfully", + "201": { + "description": "Tag created successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AddressBookRequestsDto" + "$ref": "#/components/schemas/SpaceAddressBookDto" } } } }, "400": { - "description": "Invalid space identifier" + "description": "Invalid space identifier, or the space already has 8 tags" }, "401": { - "description": "Authentication required" + "description": "Authentication required - valid JWT token must be provided" }, "403": { - "description": "User is not a member of this space" + "description": "Access forbidden - user is not an active member of this space" + }, + "404": { + "description": "Space not found" + }, + "409": { + "description": "The space has a tag with this name, ignoring case" + }, + "422": { + "description": "Invalid tag name" + }, + "429": { + "description": "Rate limit exceeded" } }, - "summary": "Get pending address book requests", + "summary": "Create address book tag", "tags": [ "spaces" ] - }, - "post": { - "description": "Creates a request to add a contact to the shared space address book. The proposed contact (name, address, chain ids) is stored on the request and added to the address book once an admin approves it.", - "operationId": "addressBookRequestsCreateRequestV1", + } + }, + "/v1/spaces/{spaceId}/address-book/tags/{tagId}": { + "patch": { + "description": "Renames a tag of the space; the tag keeps its colour. Renaming to the name of another tag of the space merges the two: the entries of the renamed tag move to the existing tag, which keeps its name and colour. Any active member of the space may rename tags.", + "operationId": "addressBooksRenameTagV1", "parameters": [ { "name": "spaceId", "required": true, "in": "path", - "description": "Space UUID", + "description": "Space UUID containing the address book", "schema": { "example": "123e4567-e89b-12d3-a456-426614174000", "type": "string" } + }, + { + "name": "tagId", + "required": true, + "in": "path", + "description": "ID of the tag to rename", + "schema": { + "type": "number" + } } ], "requestBody": { "required": true, - "description": "The contact to propose for the space address book", + "description": "The new tag name", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateAddressBookRequestDto" + "$ref": "#/components/schemas/RenameTagDto" } } } }, "responses": { - "201": { - "description": "Request created successfully", + "200": { + "description": "Tag renamed successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AddressBookRequestItemDto" + "$ref": "#/components/schemas/SpaceAddressBookDto" } } } }, "400": { - "description": "Maximum number of pending requests reached" + "description": "Invalid space or tag identifier" + }, + "401": { + "description": "Authentication required - valid JWT token must be provided" }, "403": { - "description": "User is not an active member of this space" + "description": "Access forbidden - user is not an active member of this space" }, - "409": { - "description": "A pending request for this address already exists" + "404": { + "description": "Space not found, or the tag is not a tag of this space" + }, + "422": { + "description": "Invalid tag name, or a tag identifier beyond the safe integer range" }, "429": { "description": "Rate limit exceeded" } }, - "summary": "Request to add a contact to the space address book", + "summary": "Rename address book tag", "tags": [ "spaces" ] - } - }, - "/v1/spaces/{spaceId}/address-book/requests/{requestId}/approve": { - "put": { - "description": "Admin approves a pending request. The contact is added to the shared space address book.", - "operationId": "addressBookRequestsApproveRequestV1", + }, + "delete": { + "description": "Deletes a tag of the space and removes it from every address book entry. Any active member of the space may delete tags.", + "operationId": "addressBooksDeleteTagV1", "parameters": [ { "name": "spaceId", "required": true, "in": "path", - "description": "Space UUID", + "description": "Space UUID containing the address book", "schema": { "example": "123e4567-e89b-12d3-a456-426614174000", "type": "string" } }, { - "name": "requestId", + "name": "tagId", "required": true, "in": "path", - "description": "Request ID to approve", + "description": "ID of the tag to delete", + "schema": { + "type": "number" + } + } + ], + "responses": { + "204": { + "description": "Tag deleted successfully" + }, + "400": { + "description": "Invalid space or tag identifier" + }, + "401": { + "description": "Authentication required - valid JWT token must be provided" + }, + "403": { + "description": "Access forbidden - user is not an active member of this space" + }, + "404": { + "description": "Space not found, or the tag is not a tag of this space" + }, + "422": { + "description": "A tag identifier beyond the safe integer range" + } + }, + "summary": "Delete address book tag", + "tags": [ + "spaces" + ] + } + }, + "/v1/spaces/{spaceId}/address-book/{address}": { + "delete": { + "description": "Removes a specific address from the space address book by its address.", + "operationId": "addressBooksDeleteByAddressV1", + "parameters": [ + { + "name": "spaceId", + "required": true, + "in": "path", + "description": "Space UUID containing the address book", + "schema": { + "example": "123e4567-e89b-12d3-a456-426614174000", + "type": "string" + } + }, + { + "name": "address", + "required": true, + "in": "path", + "description": "Address to remove from the address book (0x prefixed hex string)", + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "Address book entry deleted successfully" + }, + "400": { + "description": "Invalid space identifier" + }, + "403": { + "description": "Access forbidden - user is not an active admin of this space" + }, + "404": { + "description": "Space not found" + } + }, + "summary": "Delete address book entry", + "tags": [ + "spaces" + ] + } + }, + "/v1/spaces/{spaceId}/address-book/requests": { + "get": { + "description": "Retrieves pending requests to add contacts to the space address book. Admins see all pending requests, members see only their own.", + "operationId": "addressBookRequestsGetPendingRequestsV1", + "parameters": [ + { + "name": "spaceId", + "required": true, + "in": "path", + "description": "Space UUID", + "schema": { + "example": "123e4567-e89b-12d3-a456-426614174000", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Pending requests retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AddressBookRequestsDto" + } + } + } + }, + "400": { + "description": "Invalid space identifier" + }, + "401": { + "description": "Authentication required" + }, + "403": { + "description": "User is not a member of this space" + } + }, + "summary": "Get pending address book requests", + "tags": [ + "spaces" + ] + }, + "post": { + "description": "Creates a request to add a contact to the shared space address book. The proposed contact (name, address, chain ids) is stored on the request and added to the address book once an admin approves it.", + "operationId": "addressBookRequestsCreateRequestV1", + "parameters": [ + { + "name": "spaceId", + "required": true, + "in": "path", + "description": "Space UUID", + "schema": { + "example": "123e4567-e89b-12d3-a456-426614174000", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "description": "The contact to propose for the space address book", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateAddressBookRequestDto" + } + } + } + }, + "responses": { + "201": { + "description": "Request created successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AddressBookRequestItemDto" + } + } + } + }, + "400": { + "description": "Maximum number of pending requests reached" + }, + "403": { + "description": "User is not an active member of this space" + }, + "409": { + "description": "A pending request for this address already exists" + }, + "429": { + "description": "Rate limit exceeded" + } + }, + "summary": "Request to add a contact to the space address book", + "tags": [ + "spaces" + ] + } + }, + "/v1/spaces/{spaceId}/address-book/requests/{requestId}/approve": { + "put": { + "description": "Admin approves a pending request. The contact is added to the shared space address book.", + "operationId": "addressBookRequestsApproveRequestV1", + "parameters": [ + { + "name": "spaceId", + "required": true, + "in": "path", + "description": "Space UUID", + "schema": { + "example": "123e4567-e89b-12d3-a456-426614174000", + "type": "string" + } + }, + { + "name": "requestId", + "required": true, + "in": "path", + "description": "Request ID to approve", "schema": { "type": "number" } @@ -3007,6 +3413,38 @@ ] } }, + "/v1/spaces/safes": { + "get": { + "description": "Retrieves the Safes of every space the user is an active member of, one entry per space with its Safes grouped by chain like the per-space endpoint. A space without Safes has an empty `safes` object.", + "operationId": "spaceSafesGetAllV1", + "parameters": [], + "responses": { + "200": { + "description": "Safes of all spaces retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GetSpacesSafesResponse" + } + } + } + } + }, + "401": { + "description": "Authentication required" + }, + "403": { + "description": "Access forbidden - missing or invalid authentication" + } + }, + "summary": "Get Safes of all spaces", + "tags": [ + "spaces" + ] + } + }, "/v1/spaces/{spaceId}/members/invite": { "post": { "description": "Invites one or more users to join a space. Only space admins can send invitations.", @@ -3626,38 +4064,55 @@ ] } }, - "/v1/spaces/{spaceId}/surveys/{slug}/state": { + "/v1/spaces/{spaceId}/chains/{chainId}/security/{safeAddress}/recipient/{recipientAddress}": { "get": { - "description": "Returns the active survey definition and this space's response (if any) in a single round trip. Only active admins of the space can read survey state.", - "operationId": "surveysGetStateV1", + "description": "Performs real-time security analysis of a recipient address for a Safe registered to a Space, gated by the copilot_scans plan entitlement.", + "operationId": "spaceSafeShieldAnalyzeRecipientV1", "parameters": [ { - "name": "spaceId", + "name": "chainId", "required": true, "in": "path", - "description": "Space UUID to get survey state for", + "description": "Chain ID where the Safe is deployed", "schema": { - "example": "123e4567-e89b-12d3-a456-426614174000", "type": "string" } }, { - "name": "slug", + "name": "safeAddress", "required": true, "in": "path", + "description": "Safe contract address, must be registered to the Space", + "schema": { + "type": "string" + } + }, + { + "name": "recipientAddress", + "required": true, + "in": "path", + "description": "Recipient address to analyze", + "schema": { + "type": "string" + } + }, + { + "name": "spaceId", + "required": true, + "in": "path", + "description": "Space UUID", "schema": { - "example": "onboarding", "type": "string" } } ], "responses": { "200": { - "description": "", + "description": "Recipient interaction analysis results", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SurveyStateDto" + "$ref": "#/components/schemas/SingleRecipientAnalysisDto" } } } @@ -3666,533 +4121,727 @@ "description": "Invalid space identifier" }, "401": { - "description": "Not authenticated" + "description": "Authentication required" }, - "403": { - "description": "User is not an active admin of this space" + "402": { + "description": "The Space has no copilot_scans entitlement. The body carries `{ code: \"FEATURE_NOT_GRANTED\", feature }`" }, - "404": { - "description": "No active survey for this slug" + "403": { + "description": "Not a member of this Space, or the Safe is not registered to it" } }, - "summary": "Get survey state for a space", + "summary": "Analyze recipient address on a Space", "tags": [ - "surveys" + "safe-shield" ] } }, - "/v1/spaces/{spaceId}/surveys/{slug}/responses": { + "/v1/spaces/{spaceId}/chains/{chainId}/security/{safeAddress}/counterparty-analysis": { "post": { - "description": "Submits or updates the space's response to the active survey for the given slug. Only active admins of the space can submit. Idempotent: repeat submissions overwrite the previous response.", - "operationId": "surveysSubmitResponseV1", + "description": "Performs combined contract and recipient analysis for a Safe transaction on a Safe registered to a Space, gated by the copilot_scans plan entitlement.", + "operationId": "spaceSafeShieldAnalyzeCounterpartyV1", "parameters": [ { - "name": "spaceId", + "name": "chainId", "required": true, "in": "path", - "description": "Space UUID to submit a survey response for", + "description": "Chain ID where the Safe is deployed", "schema": { - "example": "123e4567-e89b-12d3-a456-426614174000", "type": "string" } }, { - "name": "slug", + "name": "safeAddress", "required": true, "in": "path", + "description": "Safe contract address, must be registered to the Space", + "schema": { + "type": "string" + } + }, + { + "name": "spaceId", + "required": true, + "in": "path", + "description": "Space UUID", "schema": { - "example": "onboarding", "type": "string" } } ], "requestBody": { "required": true, + "description": "Transaction data used to analyze all counterparties involved.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SubmitSurveyResponseDto" + "$ref": "#/components/schemas/CounterpartyAnalysisRequestDto" } } } }, "responses": { - "201": { - "description": "", + "200": { + "description": "Combined counterparty analysis including recipients and contracts grouped by status group and mapped to an address.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SurveyResponseResultDto" + "$ref": "#/components/schemas/CounterpartyAnalysisDto" } } } }, "400": { - "description": "Empty selections or unknown option keys" + "description": "Invalid space identifier" }, "401": { - "description": "Not authenticated" + "description": "Authentication required" }, - "403": { - "description": "User is not an active admin of this space" + "402": { + "description": "The Space has no copilot_scans entitlement. The body carries `{ code: \"FEATURE_NOT_GRANTED\", feature }`" }, - "404": { - "description": "No active survey for this slug" + "403": { + "description": "Not a member of this Space, or the Safe is not registered to it" } }, - "summary": "Submit a survey response for a space", + "summary": "Analyze transaction counterparties on a Space", "tags": [ - "surveys" + "safe-shield" ] } }, - "/v1/spaces/{spaceId}/entitlements": { - "get": { - "description": "The single source of truth for what a workspace can do: the active plan and per-feature entitlements, with quotas and usage for metered ones. Free-tier workspaces get the same contract shape.", - "operationId": "entitlementsGetEntitlementsV1", + "/v1/spaces/{spaceId}/chains/{chainId}/safes/{safeAddress}/policies/requests": { + "post": { + "description": "Stores the `Configuration[]` behind a `requestConfiguration(root)`, which publishes only the hash on-chain, so that the configurations a later `applyConfiguration` needs survive the delay. Call it before requesting the configuration on-chain: the root is recomputed from the configurations and has to match, but it is not required to exist on-chain yet. Idempotent: storing the same root again is a no-op.", + "operationId": "policiesCreateConfigurationRequestV1", "parameters": [ { "name": "spaceId", "required": true, "in": "path", - "description": "Space UUID", + "description": "Space UUID the Safe belongs to", "schema": { "example": "123e4567-e89b-12d3-a456-426614174000", "type": "string" } + }, + { + "name": "chainId", + "required": true, + "in": "path", + "description": "Chain ID where the Safe is deployed", + "schema": { + "example": "11155111", + "type": "string" + } + }, + { + "name": "safeAddress", + "required": true, + "in": "path", + "description": "Safe contract address, must be registered to the Space", + "schema": { + "type": "string" + } } ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreatePolicyConfigurationRequestDto" + } + } + } + }, "responses": { - "200": { + "201": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EntitlementsResponse" + "$ref": "#/components/schemas/CreatePolicyConfigurationRequestResponse" } } } }, "400": { - "description": "Invalid space identifier" + "description": "Invalid space identifier, or the Safe holds the maximum number of stored requests in this space" }, "401": { "description": "Authentication required" }, "403": { - "description": "Access forbidden - user is not a member of this space" + "description": "Access forbidden - user is not a member of this space, or the Safe is not in it" }, - "404": { - "description": "Space not found" + "422": { + "description": "Invalid chain ID, Safe address or body, or the configurations do not hash to the given root" } }, - "summary": "Get space entitlements", + "summary": "Store the configurations of a delayed configuration request", "tags": [ - "entitlements" + "spaces" ] } }, - "/v1/chains/{chainId}/owners/{ownerAddress}/safes": { + "/v1/spaces/{spaceId}/policies/active": { "get": { - "description": "Retrieves a list of Safe addresses that are owned by the specified address on a specific chain.", - "operationId": "ownersGetSafesByOwnerV1", + "description": "Returns the policies of every Safe in the Space. A Safe whose enabled modules and guards could not be read is omitted from the spending-limit and guard-enforced policies; a Safe whose delegates could not be read is omitted from the proposer policies.", + "operationId": "spacePoliciesGetActivePoliciesV1", "parameters": [ { - "name": "chainId", + "name": "spaceId", "required": true, "in": "path", - "description": "Chain ID to search for Safes", + "description": "Space UUID", "schema": { - "example": "1", + "example": "123e4567-e89b-12d3-a456-426614174000", "type": "string" } }, { - "name": "ownerAddress", + "name": "types", "required": true, - "in": "path", - "description": "Owner address to search Safes for (0x prefixed hex string)", + "in": "query", + "description": "The policy types to report, comma-separated.", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "safes", + "required": false, + "in": "query", + "description": "Narrow the read to a subset of the Space's Safes, comma-separated as `{chainId}:{safeAddress}`", "schema": { + "example": "11155111:0x0000000000000000000000000000000000000000", "type": "string" } } ], "responses": { "200": { - "description": "List of Safes owned by the specified address", + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SafeList" + "type": "array", + "items": { + "$ref": "#/components/schemas/ActivePolicyDto" + } } } } + }, + "400": { + "description": "Invalid space identifier" + }, + "403": { + "description": "Access forbidden - authentication missing or invalid, or user is not a member of this space" + }, + "422": { + "description": "Invalid CAIP-10 address, a Safe outside this space, or a missing or unknown policy type" + }, + "503": { + "description": "The policy api is unavailable" } }, - "summary": "Get Safes by owner", + "summary": "Get the active policies on Safes in a Space", "tags": [ - "owners" + "spaces" ] } }, - "/v2/owners/{ownerAddress}/safes": { + "/v1/spaces/{spaceId}/policies/pending": { "get": { - "description": "Retrieves all Safes owned by the specified address across all supported chains. Returns a map of chain IDs to arrays of Safe addresses.", - "operationId": "ownersGetAllSafesByOwnerV2", + "description": "Returns the pending policy changes of every Safe in the Space. Queued calls are detected only when made directly or one level inside a MultiSend batch, and only against known AllowanceModule and SafePolicyGuard deployments - a change made through a nested MultiSend, a custom batching contract, or a Safe module bypassing the owner queue is not detected.", + "operationId": "spacePoliciesGetPendingPoliciesV1", "parameters": [ { - "name": "ownerAddress", + "name": "spaceId", "required": true, "in": "path", - "description": "Owner address to search Safes for (0x prefixed hex string)", + "description": "Space UUID", "schema": { + "example": "123e4567-e89b-12d3-a456-426614174000", "type": "string" } + }, + { + "name": "types", + "required": true, + "in": "query", + "description": "The policy types to report, comma-separated. `spending-limit` returns queued AllowanceModule changes. A guard type (`allow`, `deny`, `cosigner`, `erc20-transfer`, `multisend`, `native-transfer`) returns the delayed `SafePolicyGuard` configurations that may set a policy of that type. `proposer` and `recovery` return none.", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "safes", + "required": false, + "in": "query", + "description": "Narrow the read to a subset of the Space's Safes, comma-separated as `{chainId}:{safeAddress}`", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "include_guard_installation", + "required": false, + "in": "query", + "description": "Also report the queued `setGuard` and `setModuleGuard` calls that install, replace or remove a `SafePolicyGuard` on each Safe, as `guard-installation` items.", + "schema": { + "default": false, + "example": true, + "type": "boolean" + } } ], "responses": { "200": { - "description": "Map of chain IDs to arrays of Safe addresses owned by the address", + "description": "", "content": { "application/json": { "schema": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - }, - "example": { - "1": [ - "0x1234567890123456789012345678901234567890" + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/PendingPolicyDto" + }, + { + "$ref": "#/components/schemas/PendingGuardInstallationDto" + }, + { + "$ref": "#/components/schemas/PendingImmediateGuardPoliciesDto" + }, + { + "$ref": "#/components/schemas/PendingDelayedGuardPoliciesDto" + } ], - "5": [ - "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd" - ] + "discriminator": { + "propertyName": "kind", + "mapping": { + "queued-transaction": "#/components/schemas/PendingPolicyDto", + "guard-installation": "#/components/schemas/PendingGuardInstallationDto", + "immediate-guard-policies": "#/components/schemas/PendingImmediateGuardPoliciesDto", + "delayed-guard-policies": "#/components/schemas/PendingDelayedGuardPoliciesDto" + } + } } } } } + }, + "400": { + "description": "Invalid space identifier" + }, + "403": { + "description": "Access forbidden - authentication missing or invalid, or user is not a member of this space" + }, + "422": { + "description": "Invalid CAIP-10 address, a Safe outside this space, a missing or unknown policy type, or an `include_guard_installation` value other than `true` or `false`" + }, + "503": { + "description": "The policy api is unavailable" } }, - "summary": "Get all Safes by owner", + "summary": "Get the pending policy changes on Safes in a Space", "tags": [ - "owners" + "spaces" ] } }, - "/v3/owners/{ownerAddress}/safes": { + "/v1/spaces/{spaceId}/surveys/{slug}/state": { "get": { - "description": "Retrieves all Safes owned by the specified address across all supported chains. Returns a map of chain IDs to arrays of Safe addresses.", - "operationId": "ownersGetAllSafesByOwnerV3", + "description": "Returns the active survey definition and this space's response (if any) in a single round trip. Only active admins of the space can read survey state.", + "operationId": "surveysGetStateV1", "parameters": [ { - "name": "ownerAddress", + "name": "spaceId", + "required": true, + "in": "path", + "description": "Space UUID to get survey state for", + "schema": { + "example": "123e4567-e89b-12d3-a456-426614174000", + "type": "string" + } + }, + { + "name": "slug", "required": true, "in": "path", - "description": "Owner address to search Safes for (0x prefixed hex string)", "schema": { + "example": "onboarding", "type": "string" } } ], "responses": { "200": { - "description": "Map of chain IDs to arrays of Safe addresses owned by the address", + "description": "", "content": { "application/json": { "schema": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - }, - "example": { - "1": [ - "0x1234567890123456789012345678901234567890" - ], - "5": [ - "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd" - ] - } + "$ref": "#/components/schemas/SurveyStateDto" } } } + }, + "400": { + "description": "Invalid space identifier" + }, + "401": { + "description": "Not authenticated" + }, + "403": { + "description": "User is not an active admin of this space" + }, + "404": { + "description": "No active survey for this slug" } }, - "summary": "Get all Safes by owner", + "summary": "Get survey state for a space", "tags": [ - "owners" + "surveys" ] } }, - "/v1/chains/{chainId}/relay": { + "/v1/spaces/{spaceId}/surveys/{slug}/responses": { "post": { - "description": "Relays a Safe transaction or Safe creation transaction using the relay service, which pays for gas fees. Supports execTransaction (Safe tx) and createProxyWithNonce (Safe creation) calldata. On relay-fee chains, safeTxHash is required and must match the hash derived on-chain from the submitted calldata. On chains where pre-relay Tenderly simulation is enabled, an execTransaction is simulated before being submitted: a confirmed revert returns SIMULATION_FAILED, and an unreachable simulator returns INDETERMINATE_SIMULATION (retry with acceptUnverifiedSimulation=true to proceed anyway when the simulator is unreachable).", - "operationId": "relayRelayV1", + "description": "Submits or updates the space's response to the active survey for the given slug. Only active admins of the space can submit. Idempotent: repeat submissions overwrite the previous response.", + "operationId": "surveysSubmitResponseV1", "parameters": [ { - "name": "chainId", + "name": "spaceId", "required": true, "in": "path", - "description": "Chain ID where the Safe transaction will be executed", + "description": "Space UUID to submit a survey response for", "schema": { - "example": "1", + "example": "123e4567-e89b-12d3-a456-426614174000", + "type": "string" + } + }, + { + "name": "slug", + "required": true, + "in": "path", + "schema": { + "example": "onboarding", "type": "string" } } ], "requestBody": { "required": true, - "description": "Transaction data to relay. safeTxHash is required on relay-fee chains and must correspond to the to + data fields. Set acceptUnverifiedSimulation=true to retry a relay skipping the simulation which previously returned INDETERMINATE_SIMULATION.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RelayDto" + "$ref": "#/components/schemas/SubmitSurveyResponseDto" } } } }, "responses": { - "200": { - "description": "Transaction relayed successfully", + "201": { + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Relay" + "$ref": "#/components/schemas/SurveyResponseResultDto" } } } }, "400": { - "description": "Request body failed schema validation" + "description": "Empty selections or unknown option keys" + }, + "401": { + "description": "Not authenticated" }, "403": { - "description": "Relay denied: safeTxHash missing, fee service rejected, or unofficial proxy factory" + "description": "User is not an active admin of this space" }, - "422": { - "description": "Relay rejected. The consumers MUST branch on the `code` field; `message` is informational. Possible cases: safeTxHash does not match the transaction data, unrecognised transaction type, SIMULATION_FAILED (Tenderly confirmed revert), or INDETERMINATE_SIMULATION (simulator unreachable; retry with `acceptUnverifiedSimulation=true` to proceed anyway).", - "schema": { - "examples": { - "simulationFailed": { - "summary": "SIMULATION_FAILED", - "value": { - "code": "SIMULATION_FAILED", - "message": "Relay denied: transaction simulation failed: Reverted with reason string: 'GS013'", - "statusCode": 422 - } - }, - "indeterminateSimulation": { - "summary": "INDETERMINATE_SIMULATION", - "value": { - "code": "INDETERMINATE_SIMULATION", - "message": "Relay simulation could not be completed.", - "statusCode": 422 - } - }, - "safeTxHashMismatch": { - "summary": "safeTxHash mismatch (no `code`)", - "value": { - "message": "Safe transaction hash mismatch: provided hash 0x... does not match the transaction data", - "statusCode": 422 - } - } - } - }, + "404": { + "description": "No active survey for this slug" + } + }, + "summary": "Submit a survey response for a space", + "tags": [ + "surveys" + ] + } + }, + "/v1/spaces/entitlements": { + "get": { + "description": "The entitlements of every workspace the user is an active member of, keyed by workspace UUID. Each value is what the per-workspace endpoint returns.", + "operationId": "entitlementsGetAllEntitlementsV1", + "parameters": [], + "responses": { + "200": { + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RelayErrorResponse" + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/EntitlementsResponse" + } } } } }, - "429": { - "description": "Relay limit reached for this Safe" + "401": { + "description": "Authentication required" + }, + "403": { + "description": "Access forbidden - missing or invalid authentication" } }, - "summary": "Relay transaction", + "summary": "Get entitlements of all spaces", "tags": [ - "relay" + "entitlements" ] } }, - "/v1/chains/{chainId}/relay/status/{taskId}": { + "/v1/spaces/{spaceId}/entitlements": { "get": { - "description": "Retrieves the status of a relay task from the relay provider. This is a proxy endpoint to securely query task status without exposing the API key.", - "operationId": "relayGetTaskStatusV1", + "description": "The single source of truth for what a workspace can do: the active plan and per-feature entitlements, with quotas and usage for metered ones. Free-tier workspaces get the same contract shape.", + "operationId": "entitlementsGetEntitlementsV1", "parameters": [ { - "name": "chainId", - "required": true, - "in": "path", - "description": "Chain ID associated with the relay task", - "schema": { - "example": "11155111", - "type": "string" - } - }, - { - "name": "taskId", + "name": "spaceId", "required": true, "in": "path", - "description": "Task ID returned from the relay transaction", + "description": "Space UUID", "schema": { + "example": "123e4567-e89b-12d3-a456-426614174000", "type": "string" } } ], "responses": { "200": { - "description": "Task status retrieved successfully", + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RelayTaskStatus" + "$ref": "#/components/schemas/EntitlementsResponse" } } } }, + "400": { + "description": "Invalid space identifier" + }, + "401": { + "description": "Authentication required" + }, + "403": { + "description": "Access forbidden - user is not a member of this space" + }, "404": { - "description": "Task not found" + "description": "Space not found" } }, - "summary": "Get relay task status", + "summary": "Get space entitlements", "tags": [ - "relay" + "entitlements" ] } }, - "/v1/chains/{chainId}/relay/{safeAddress}": { - "get": { - "description": "Retrieves the number of remaining relay transactions available for a specific Safe on the given chain. On relay-fee chains, safeTxHash is forwarded to the fee service to determine per-transaction eligibility (returns remaining=1 when eligible, 0 when not). On daily-limit and no-fee-campaign chains, a count-based quota is returned.", - "operationId": "relayGetRelaysRemainingV1", + "/v1/spaces/{spaceId}/chains/{chainId}/relay": { + "post": { + "description": "Relays a Safe transaction against the workspace's sponsored-transaction allowance, which its plan grants and this spends one unit of per call — a batch included. The chain must list SUBSCRIPTION among its gas payment options; no other option applies here. A call acting on an existing Safe is admitted only for a Safe the workspace holds; a Safe creation or a passkey signer deployment, having no Safe yet, is admitted as it is there.", + "operationId": "spaceRelayRelayV1", "parameters": [ { "name": "chainId", "required": true, "in": "path", - "description": "Chain ID where the Safe is deployed", + "description": "Chain ID where the Safe transaction will be executed", "schema": { "example": "1", "type": "string" } }, { - "name": "safeAddress", + "name": "spaceId", "required": true, "in": "path", - "description": "Safe contract address (0x prefixed hex string)", - "schema": { - "type": "string" - } - }, - { - "name": "safeTxHash", - "required": false, - "in": "query", - "description": "Safe transaction hash (0x prefixed hex string). Required on relay-fee chains to check per-transaction eligibility with the fee service. Optional on daily-limit and no-fee-campaign chains.", + "description": "Space UUID", "schema": { + "example": "123e4567-e89b-12d3-a456-426614174000", "type": "string" } } ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SpaceRelayDto" + } + } + } + }, "responses": { - "200": { - "description": "Remaining relay quota retrieved successfully", + "201": { + "description": "Transaction relayed", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RelaysRemaining" + "$ref": "#/components/schemas/Relay" + } + } + } + }, + "400": { + "description": "Malformed workspace identifier" + }, + "401": { + "description": "Authentication required" + }, + "402": { + "description": "The workspace's sponsored-transaction allowance is spent. The body carries `quota`, `used` and `resetsAt` so a client can offer to pay for the transaction itself." + }, + "403": { + "description": "Not a member of the workspace, or the transaction was denied" + }, + "404": { + "description": "Workspace not found" + }, + "409": { + "description": "SUBSCRIPTION cannot pay for this request: the chain does not list it or has no relayer, the Safe is not one the workspace holds, or the transaction refunds gas (`gasPrice` > 0).", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GasPaymentOptionUnavailableResponse" } } } + }, + "422": { + "description": "Request failed schema validation, or the transaction was simulated and would revert (SIMULATION_FAILED) or could not be simulated (INDETERMINATE_SIMULATION)" } }, - "summary": "Get remaining relays", + "summary": "Relay a transaction at a workspace's expense", "tags": [ "relay" ] } }, - "/v1/chains/{chainId}/safe-apps": { - "get": { - "description": "Retrieves a list of Safe Apps available for a specific chain, with optional filtering by client URL or app URL.", - "operationId": "safeAppsGetSafeAppsV1", + "/v1/spaces/{spaceId}/chains/{chainId}/safes/{safeAddress}/safenet/checks": { + "post": { + "description": "Queues a Safenet check of a pending Safe transaction that an owner has signed. Safe Labs pays the fee and counts the check against the workspace in the path. The caller must be an active member of that workspace, the workspace must hold the Safe and its plan must grant policies (Business and Enterprise), and the chain must list SAFENET_CHECKS.", + "operationId": "safenetChecksRequestCheckV1", "parameters": [ { "name": "chainId", "required": true, "in": "path", - "description": "Chain ID to get Safe Apps for", + "description": "Chain ID where the Safe is deployed", "schema": { "example": "1", "type": "string" } }, { - "name": "clientUrl", - "required": false, - "in": "query", - "description": "Filter by client URL to get apps compatible with specific client", + "name": "safeAddress", + "required": true, + "in": "path", + "description": "Safe contract address (0x prefixed hex string)", "schema": { "type": "string" } }, { - "name": "url", - "required": false, - "in": "query", - "description": "Filter by specific Safe App URL", + "name": "spaceId", + "required": true, + "in": "path", + "description": "Space UUID", "schema": { + "example": "123e4567-e89b-12d3-a456-426614174000", "type": "string" } } ], - "responses": { - "200": { - "description": "List of Safe Apps available for the specified chain", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SafeApp" - } - } + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateSafenetCheckDto" } } } }, - "summary": "Get Safe Apps", + "responses": { + "202": { + "description": "Queued, or already queued" + }, + "400": { + "description": "Malformed workspace identifier" + }, + "401": { + "description": "Authentication required" + }, + "402": { + "description": "The workspace plan does not grant policies, which Safenet checks share. The body carries `{ code: \"FEATURE_NOT_GRANTED\", feature }`" + }, + "403": { + "description": "Not a member of the workspace, or the workspace does not hold the Safe" + }, + "404": { + "description": "Workspace not found, or no such transaction for this Safe" + }, + "422": { + "description": "The Safe is older than 1.3.0, or the transaction is executed or stale, unsigned by an owner, or of another Safe" + }, + "429": { + "description": "The workspace has used its daily limit of sponsored Safenet checks" + }, + "501": { + "description": "Safenet checks are not available on this chain" + } + }, + "summary": "Request a Safenet check at a workspace expense", "tags": [ - "safe-apps" + "safenet" ] } }, - "/v1/chains/{chainId}/safes/{safeAddress}": { + "/v1/chains/{chainId}/owners/{ownerAddress}/safes": { "get": { - "description": "Retrieves detailed information about a Safe including owners, threshold, modules, and current state.", - "operationId": "safesGetSafeV1", + "description": "Retrieves a list of Safe addresses that are owned by the specified address on a specific chain.", + "operationId": "ownersGetSafesByOwnerV1", "parameters": [ { "name": "chainId", "required": true, "in": "path", - "description": "Chain ID where the Safe is deployed", + "description": "Chain ID to search for Safes", "schema": { "example": "1", "type": "string" } }, { - "name": "safeAddress", + "name": "ownerAddress", "required": true, "in": "path", - "description": "Safe contract address (0x prefixed hex string)", + "description": "Owner address to search Safes for (0x prefixed hex string)", "schema": { "type": "string" } @@ -4200,45 +4849,32 @@ ], "responses": { "200": { - "description": "Safe information retrieved successfully", + "description": "List of Safes owned by the specified address", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SafeState" + "$ref": "#/components/schemas/SafeList" } } } - }, - "404": { - "description": "Safe not found on the specified chain" } }, - "summary": "Get Safe information", + "summary": "Get Safes by owner", "tags": [ - "safes" + "owners" ] } }, - "/v1/chains/{chainId}/safes/{safeAddress}/nonces": { + "/v2/owners/{ownerAddress}/safes": { "get": { - "description": "Retrieves the current nonces for a Safe, including the transaction nonce and any queued nonces.", - "operationId": "safesGetNoncesV1", + "description": "Retrieves all Safes owned by the specified address across all supported chains. Returns a map of chain IDs to arrays of Safe addresses.", + "operationId": "ownersGetAllSafesByOwnerV2", "parameters": [ { - "name": "chainId", - "required": true, - "in": "path", - "description": "Chain ID where the Safe is deployed", - "schema": { - "example": "1", - "type": "string" - } - }, - { - "name": "safeAddress", + "name": "ownerAddress", "required": true, "in": "path", - "description": "Safe contract address (0x prefixed hex string)", + "description": "Owner address to search Safes for (0x prefixed hex string)", "schema": { "type": "string" } @@ -4246,75 +4882,46 @@ ], "responses": { "200": { - "description": "Safe nonces retrieved successfully", + "description": "Map of chain IDs to arrays of Safe addresses owned by the address", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SafeNonces" + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + }, + "example": { + "1": [ + "0x1234567890123456789012345678901234567890" + ], + "5": [ + "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd" + ] + } } } } - }, - "404": { - "description": "Safe not found on the specified chain" } }, - "summary": "Get Safe nonces", + "summary": "Get all Safes by owner", "tags": [ - "safes" + "owners" ] } }, - "/v1/safes": { + "/v3/owners/{ownerAddress}/safes": { "get": { - "description": "Retrieves an overview of multiple Safes including their balances, transaction counts, and other summary information. Supports cross-chain queries using CAIP-10 address format.", - "operationId": "safesGetSafeOverviewV1", + "description": "Retrieves all Safes owned by the specified address across all supported chains. Returns a map of chain IDs to arrays of Safe addresses.", + "operationId": "ownersGetAllSafesByOwnerV3", "parameters": [ { - "name": "currency", - "required": true, - "in": "query", - "description": "Fiat currency code for balance conversion (e.g., USD, EUR)", - "schema": { - "example": "USD", - "type": "string" - } - }, - { - "name": "safes", + "name": "ownerAddress", "required": true, - "in": "query", - "description": "Comma-separated list of Safe addresses in CAIP-10 format (chainId:address)", - "schema": { - "example": "1:0x1234567890123456789012345678901234567890,5:0xabcdefabcdefabcdefabcdefabcdefabcdefabcd", - "type": "string" - } - }, - { - "name": "trusted", - "required": false, - "in": "query", - "description": "If true, only includes trusted tokens in balance calculations", - "schema": { - "example": false, - "type": "boolean" - } - }, - { - "name": "exclude_spam", - "required": false, - "in": "query", - "description": "If true, excludes spam tokens from balance calculations", - "schema": { - "example": true, - "type": "boolean" - } - }, - { - "name": "wallet_address", - "required": false, - "in": "query", - "description": "Optional wallet address to filter Safes where this address is an owner", + "in": "path", + "description": "Owner address to search Safes for (0x prefixed hex string)", "schema": { "type": "string" } @@ -4322,120 +4929,157 @@ ], "responses": { "200": { - "description": "Array of Safe overviews with balances and metadata", + "description": "Map of chain IDs to arrays of Safe addresses owned by the address", "content": { "application/json": { "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SafeOverview" + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + }, + "example": { + "1": [ + "0x1234567890123456789012345678901234567890" + ], + "5": [ + "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd" + ] } } } } } }, - "summary": "Get Safe overview", + "summary": "Get all Safes by owner", "tags": [ - "safes" + "owners" ] } }, - "/v2/safes": { - "get": { - "description": "Retrieves an overview of multiple Safes. Supports cross-chain queries using chainId:address format.", - "operationId": "safesGetSafeOverviewV2", + "/v1/chains/{chainId}/relay": { + "post": { + "description": "Relays a Safe transaction or Safe creation transaction using the relay service, which pays for gas fees. Supports execTransaction (Safe tx) and createProxyWithNonce (Safe creation) calldata. On relay-fee chains, safeTxHash is required and must match the hash derived on-chain from the submitted calldata. On chains where pre-relay Tenderly simulation is enabled, an execTransaction is simulated before being submitted: a confirmed revert returns SIMULATION_FAILED, and an unreachable simulator returns INDETERMINATE_SIMULATION (retry with acceptUnverifiedSimulation=true to proceed anyway when the simulator is unreachable).", + "operationId": "relayRelayV1", "parameters": [ { - "name": "currency", - "required": true, - "in": "query", - "description": "Fiat currency code for balance conversion (e.g., USD, EUR)", - "schema": { - "example": "USD", - "type": "string" - } - }, - { - "name": "safes", + "name": "chainId", "required": true, - "in": "query", - "description": "Comma-separated list of Safe addresses in chainId:address format", - "schema": { - "example": "1:0x1234567890123456789012345678901234567890,5:0xabcdefabcdefabcdefabcdefabcdefabcdefabcd", - "type": "string" - } - }, - { - "name": "trusted", - "required": false, - "in": "query", - "description": "If true, only includes trusted tokens in balance calculations.", - "schema": { - "example": false, - "type": "boolean" - } - }, - { - "name": "wallet_address", - "required": false, - "in": "query", - "description": "Optional wallet address to filter Safes where this address is an owner", + "in": "path", + "description": "Chain ID where the Safe transaction will be executed", "schema": { + "example": "1", "type": "string" } } ], + "requestBody": { + "required": true, + "description": "Transaction data to relay. safeTxHash is required on relay-fee chains and must correspond to the to + data fields. Set acceptUnverifiedSimulation=true to retry a relay skipping the simulation which previously returned INDETERMINATE_SIMULATION.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RelayDto" + } + } + } + }, "responses": { "200": { - "description": "Array of Safe overviews with balances and metadata", + "description": "Transaction relayed successfully", "content": { "application/json": { "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SafeOverview" + "$ref": "#/components/schemas/Relay" + } + } + } + }, + "400": { + "description": "Request body failed schema validation" + }, + "403": { + "description": "Relay denied: safeTxHash missing, fee service rejected, or unofficial proxy factory" + }, + "409": { + "description": "A transaction that refunds gas (`gasPrice` > 0) needs PAY_FROM_SAFE, which the chain does not offer.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GasPaymentOptionUnavailableResponse" + } + } + } + }, + "422": { + "description": "Relay rejected. The consumers MUST branch on the `code` field; `message` is informational. Possible cases: safeTxHash does not match the transaction data, unrecognised transaction type, SIMULATION_FAILED (Tenderly confirmed revert), or INDETERMINATE_SIMULATION (simulator unreachable; retry with `acceptUnverifiedSimulation=true` to proceed anyway).", + "schema": { + "examples": { + "simulationFailed": { + "summary": "SIMULATION_FAILED", + "value": { + "code": "SIMULATION_FAILED", + "message": "Relay denied: transaction simulation failed: Reverted with reason string: 'GS013'", + "statusCode": 422 + } + }, + "indeterminateSimulation": { + "summary": "INDETERMINATE_SIMULATION", + "value": { + "code": "INDETERMINATE_SIMULATION", + "message": "Relay simulation could not be completed.", + "statusCode": 422 + } + }, + "safeTxHashMismatch": { + "summary": "safeTxHash mismatch (no `code`)", + "value": { + "message": "Safe transaction hash mismatch: provided hash 0x... does not match the transaction data", + "statusCode": 422 } } } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RelayErrorResponse" + } + } } + }, + "429": { + "description": "Relay limit reached for this Safe" } }, - "summary": "Get Safe overview (v2)", + "summary": "Relay transaction", "tags": [ - "safes" + "relay" ] } }, - "/v1/chains/{chainId}/security/{safeAddress}/recipient/{recipientAddress}": { + "/v1/chains/{chainId}/relay/status/{taskId}": { "get": { - "description": "Performs real-time security analysis of a recipient address for a specific Safe. Returns analysis results grouped by status group, sorted by severity (CRITICAL first).", - "operationId": "safeShieldAnalyzeRecipientV1", + "description": "Retrieves the status of a relay task from the relay provider. This is a proxy endpoint to securely query task status without exposing the API key.", + "operationId": "relayGetTaskStatusV1", "parameters": [ { "name": "chainId", "required": true, "in": "path", - "description": "Chain ID where the Safe is deployed", - "schema": { - "example": "1", - "type": "string" - } - }, - { - "name": "safeAddress", - "required": true, - "in": "path", - "description": "Safe contract address", + "description": "Chain ID associated with the relay task", "schema": { + "example": "11155111", "type": "string" } }, { - "name": "recipientAddress", + "name": "taskId", "required": true, "in": "path", - "description": "Recipient address to analyze", + "description": "Task ID returned from the relay transaction", "schema": { "type": "string" } @@ -4443,26 +5087,29 @@ ], "responses": { "200": { - "description": "Recipient interaction analysis results", + "description": "Task status retrieved successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SingleRecipientAnalysisDto" + "$ref": "#/components/schemas/RelayTaskStatus" } } } + }, + "404": { + "description": "Task not found" } }, - "summary": "Analyze recipient address", + "summary": "Get relay task status", "tags": [ - "safe-shield" + "relay" ] } }, - "/v1/chains/{chainId}/security/{safeAddress}/counterparty-analysis": { - "post": { - "description": "Performs combined contract and recipient analysis for a Safe transaction. Returns both analyses grouped by status group for each counterparty.", - "operationId": "safeShieldAnalyzeCounterpartyV1", + "/v1/chains/{chainId}/relay/{safeAddress}": { + "get": { + "description": "Retrieves the free relays left for a specific Safe on the given chain: the no-fee campaign quota where the chain lists NO_FEE_CAMPAIGN, otherwise the daily limit where it lists FREE_DAILY_LIMIT.", + "operationId": "relayGetRelaysRemainingV1", "parameters": [ { "name": "chainId", @@ -4478,98 +5125,101 @@ "name": "safeAddress", "required": true, "in": "path", - "description": "Safe contract address", + "description": "Safe contract address (0x prefixed hex string)", "schema": { "type": "string" } - } - ], - "requestBody": { - "required": true, - "description": "Transaction data used to analyze all counterparties involved.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CounterpartyAnalysisRequestDto" - } + }, + { + "name": "safeTxHash", + "required": false, + "in": "query", + "description": "Safe transaction hash (0x prefixed hex string). Ignored; kept so existing clients do not break.", + "schema": { + "type": "string" } } - }, + ], "responses": { "200": { - "description": "Combined counterparty analysis including recipients and contracts grouped by status group and mapped to an address.", + "description": "Remaining relay quota retrieved successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CounterpartyAnalysisDto" + "$ref": "#/components/schemas/RelaysRemaining" } } } + }, + "403": { + "description": "The chain has no relayer or lists no free option, such as a chain that only lists PAY_FROM_SAFE" } }, - "summary": "Analyze transaction counterparties", + "summary": "Get remaining relays", "tags": [ - "safe-shield" + "relay" ] } }, - "/v1/chains/{chainId}/security/{safeAddress}/threat-analysis": { - "post": { - "description": "Performs real-time threat analysis for a Safe transaction.", - "operationId": "safeShieldAnalyzeThreatV1", + "/v1/chains/{chainId}/safe-apps": { + "get": { + "description": "Retrieves a list of Safe Apps available for a specific chain, with optional filtering by client URL or app URL.", + "operationId": "safeAppsGetSafeAppsV1", "parameters": [ { "name": "chainId", "required": true, "in": "path", - "description": "Chain ID where the Safe is deployed", + "description": "Chain ID to get Safe Apps for", "schema": { + "example": "1", "type": "string" } }, { - "name": "safeAddress", - "required": true, - "in": "path", - "description": "Safe contract address", + "name": "clientUrl", + "required": false, + "in": "query", + "description": "Filter by client URL to get apps compatible with specific client", "schema": { "type": "string" } - } - ], - "requestBody": { - "required": true, - "description": "EIP-712 typed data and wallet information for threat analysis.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ThreatAnalysisRequestDto" - } + }, + { + "name": "url", + "required": false, + "in": "query", + "description": "Filter by specific Safe App URL", + "schema": { + "type": "string" } } - }, + ], "responses": { "200": { - "description": "Threat analysis results including threat findings and balance changes.", + "description": "List of Safe Apps available for the specified chain", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ThreatAnalysisResponseDto" + "type": "array", + "items": { + "$ref": "#/components/schemas/SafeApp" + } } } } } }, - "summary": "Analyze transaction threat", + "summary": "Get Safe Apps", "tags": [ - "safe-shield" + "safe-apps" ] } }, - "/v1/chains/{chainId}/security/{safeAddress}/report-false-result": { - "post": { - "description": "Reports a FALSE_POSITIVE or FALSE_NEGATIVE Blockaid transaction scan result for review. Use the request_id from the original scan response to identify the transaction.", - "operationId": "safeShieldReportFalseResultV1", + "/v1/chains/{chainId}/safes/{safeAddress}": { + "get": { + "description": "Retrieves detailed information about a Safe including owners, threshold, modules, and current state.", + "operationId": "safesGetSafeV1", "parameters": [ { "name": "chainId", @@ -4585,58 +5235,45 @@ "name": "safeAddress", "required": true, "in": "path", - "description": "Safe contract address", + "description": "Safe contract address (0x prefixed hex string)", "schema": { "type": "string" } } ], - "requestBody": { - "required": true, - "description": "Report details including event type, request_id from scan response, and details.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ReportFalseResultRequestDto" - } - } - } - }, "responses": { "200": { - "description": "Report submitted successfully.", + "description": "Safe information retrieved successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ReportFalseResultResponseDto" + "$ref": "#/components/schemas/SafeState" } } } + }, + "404": { + "description": "Safe not found on the specified chain" } }, - "summary": "Report false Blockaid scan result", + "summary": "Get Safe information", "tags": [ - "safe-shield" + "safes" ] } }, - "/v1/targeted-messaging/outreaches/{outreachId}/chains/{chainId}/safes/{safeAddress}": { + "/v1/chains/{chainId}/safes/{safeAddress}/nonces": { "get": { - "operationId": "targetedMessagingGetTargetedSafeV1", + "description": "Retrieves the current nonces for a Safe, including the transaction nonce and any queued nonces.", + "operationId": "safesGetNoncesV1", "parameters": [ - { - "name": "outreachId", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - }, { "name": "chainId", "required": true, "in": "path", + "description": "Chain ID where the Safe is deployed", "schema": { + "example": "1", "type": "string" } }, @@ -4644,6 +5281,7 @@ "name": "safeAddress", "required": true, "in": "path", + "description": "Safe contract address (0x prefixed hex string)", "schema": { "type": "string" } @@ -4651,56 +5289,75 @@ ], "responses": { "200": { - "description": "", + "description": "Safe nonces retrieved successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TargetedSafe" + "$ref": "#/components/schemas/SafeNonces" } } } }, "404": { - "description": "Safe not targeted." + "description": "Safe not found on the specified chain" } }, + "summary": "Get Safe nonces", "tags": [ - "targeted-messaging" + "safes" ] } }, - "/v1/targeted-messaging/outreaches/{outreachId}/chains/{chainId}/safes/{safeAddress}/signers/{signerAddress}/submissions": { + "/v1/safes": { "get": { - "operationId": "targetedMessagingGetSubmissionV1", + "description": "Retrieves an overview of multiple Safes including their balances, transaction counts, and other summary information. Supports cross-chain queries using CAIP-10 address format.", + "operationId": "safesGetSafeOverviewV1", "parameters": [ { - "name": "outreachId", + "name": "currency", "required": true, - "in": "path", + "in": "query", + "description": "Fiat currency code for balance conversion (e.g., USD, EUR)", "schema": { - "type": "number" + "example": "USD", + "type": "string" } }, { - "name": "chainId", + "name": "safes", "required": true, - "in": "path", + "in": "query", + "description": "Comma-separated list of Safe addresses in CAIP-10 format (chainId:address)", "schema": { + "example": "1:0x1234567890123456789012345678901234567890,5:0xabcdefabcdefabcdefabcdefabcdefabcdefabcd", "type": "string" } }, { - "name": "safeAddress", - "required": true, - "in": "path", + "name": "trusted", + "required": false, + "in": "query", + "description": "If true, only includes trusted tokens in balance calculations", "schema": { - "type": "string" + "example": false, + "type": "boolean" } }, { - "name": "signerAddress", - "required": true, - "in": "path", + "name": "exclude_spam", + "required": false, + "in": "query", + "description": "If true, excludes spam tokens from balance calculations", + "schema": { + "example": true, + "type": "boolean" + } + }, + { + "name": "wallet_address", + "required": false, + "in": "query", + "description": "Optional wallet address to filter Safes where this address is an owner", "schema": { "type": "string" } @@ -4708,134 +5365,150 @@ ], "responses": { "200": { - "description": "", + "description": "Array of Safe overviews with balances and metadata", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Submission" + "type": "array", + "items": { + "$ref": "#/components/schemas/SafeOverview" + } } } } } }, + "summary": "Get Safe overview", "tags": [ - "targeted-messaging" + "safes" ] - }, - "post": { - "operationId": "targetedMessagingCreateSubmissionV1", + } + }, + "/v2/safes": { + "get": { + "description": "Retrieves an overview of multiple Safes. Supports cross-chain queries using chainId:address format.", + "operationId": "safesGetSafeOverviewV2", "parameters": [ { - "name": "outreachId", + "name": "currency", "required": true, - "in": "path", + "in": "query", + "description": "Fiat currency code for balance conversion (e.g., USD, EUR)", "schema": { - "type": "number" + "example": "USD", + "type": "string" } }, { - "name": "chainId", + "name": "safes", "required": true, - "in": "path", + "in": "query", + "description": "Comma-separated list of Safe addresses in chainId:address format", "schema": { + "example": "1:0x1234567890123456789012345678901234567890,5:0xabcdefabcdefabcdefabcdefabcdefabcdefabcd", "type": "string" } }, { - "name": "safeAddress", - "required": true, - "in": "path", - "schema": { - "type": "string" + "name": "trusted", + "required": false, + "in": "query", + "description": "If true, only includes trusted tokens in balance calculations.", + "schema": { + "example": false, + "type": "boolean" } }, { - "name": "signerAddress", - "required": true, - "in": "path", + "name": "wallet_address", + "required": false, + "in": "query", + "description": "Optional wallet address to filter Safes where this address is an owner", "schema": { "type": "string" } } ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateSubmissionDto" - } - } - } - }, "responses": { - "201": { - "description": "", + "200": { + "description": "Array of Safe overviews with balances and metadata", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Submission" + "type": "array", + "items": { + "$ref": "#/components/schemas/SafeOverview" + } } } } } }, + "summary": "Get Safe overview (v2)", "tags": [ - "targeted-messaging" + "safes" ] } }, - "/v1/chains/{chainId}/transactions/{id}": { + "/v1/chains/{chainId}/security/{safeAddress}/recipient/{recipientAddress}": { "get": { - "description": "Retrieves detailed information about a specific transaction by its ID, including execution status, confirmations, and decoded transaction data.", - "operationId": "transactionsGetTransactionByIdV1", + "description": "Performs real-time security analysis of a recipient address for a specific Safe. Returns analysis results grouped by status group, sorted by severity (CRITICAL first).", + "operationId": "safeShieldAnalyzeRecipientV1", "parameters": [ { "name": "chainId", "required": true, "in": "path", - "description": "Chain ID where the transaction exists", + "description": "Chain ID where the Safe is deployed", "schema": { "example": "1", "type": "string" } }, { - "name": "id", + "name": "safeAddress", "required": true, "in": "path", - "description": "Transaction ID (safe transaction hash or multisig transaction ID)", + "description": "Safe contract address", + "schema": { + "type": "string" + } + }, + { + "name": "recipientAddress", + "required": true, + "in": "path", + "description": "Recipient address to analyze", "schema": { - "example": "multisig_0x1234567890123456789012345678901234567890_0x5678...", "type": "string" } } ], "responses": { "200": { - "description": "Transaction details retrieved successfully", + "description": "Recipient interaction analysis results", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TransactionDetails" + "$ref": "#/components/schemas/SingleRecipientAnalysisDto" } } } }, - "404": { - "description": "Transaction not found" + "402": { + "description": "Disabled on Core. The body carries `{ code: \"SAFE_SHIELD_DISABLED_ON_CORE\", message }`." } }, - "summary": "Get transaction details", + "summary": "Analyze recipient address", "tags": [ - "transactions" + "safe-shield" ] } }, - "/v1/chains/{chainId}/safes/{safeAddress}/multisig-transactions": { - "get": { - "description": "Retrieves a paginated list of multisig transactions for a Safe with optional filtering by execution date, recipient, value, nonce, and execution status.", - "operationId": "transactionsGetMultisigTransactionsV1", + "/v1/chains/{chainId}/security/{safeAddress}/counterparty-analysis": { + "post": { + "description": "Performs combined contract and recipient analysis for a Safe transaction. Returns both analyses grouped by status group for each counterparty.", + "operationId": "safeShieldAnalyzeCounterpartyV1", "parameters": [ { "name": "chainId", @@ -4851,113 +5524,114 @@ "name": "safeAddress", "required": true, "in": "path", - "description": "Safe contract address (0x prefixed hex string)", - "schema": { - "type": "string" - } - }, - { - "name": "execution_date__gte", - "required": false, - "in": "query", - "description": "Filter by execution date greater than or equal to (ISO 8601 format)", - "schema": { - "type": "string" - } - }, - { - "name": "execution_date__lte", - "required": false, - "in": "query", - "description": "Filter by execution date less than or equal to (ISO 8601 format)", + "description": "Safe contract address", "schema": { "type": "string" } - }, - { - "name": "to", - "required": false, - "in": "query", - "description": "Filter by recipient address (0x prefixed hex string)", - "schema": { - "type": "string" + } + ], + "requestBody": { + "required": true, + "description": "Transaction data used to analyze all counterparties involved.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CounterpartyAnalysisRequestDto" + } } - }, - { - "name": "value", - "required": false, - "in": "query", - "description": "Filter by transaction value in wei", - "schema": { - "type": "string" + } + }, + "responses": { + "200": { + "description": "Combined counterparty analysis including recipients and contracts grouped by status group and mapped to an address.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CounterpartyAnalysisDto" + } + } } - }, + } + }, + "summary": "Analyze transaction counterparties", + "tags": [ + "safe-shield" + ] + } + }, + "/v1/chains/{chainId}/security/{safeAddress}/threat-analysis": { + "post": { + "description": "Performs real-time threat analysis for a Safe transaction.", + "operationId": "safeShieldAnalyzeThreatV1", + "parameters": [ { - "name": "nonce", - "required": false, - "in": "query", - "description": "Filter by transaction nonce", + "name": "chainId", + "required": true, + "in": "path", + "description": "Chain ID where the Safe is deployed", "schema": { "type": "string" } }, { - "name": "executed", - "required": false, - "in": "query", - "description": "Filter by execution status (true for executed, false for pending)", - "schema": { - "type": "boolean" - } - }, - { - "name": "cursor", - "required": false, - "in": "query", - "description": "Pagination cursor for retrieving the next set of results", + "name": "safeAddress", + "required": true, + "in": "path", + "description": "Safe contract address", "schema": { "type": "string" } } ], + "requestBody": { + "required": true, + "description": "EIP-712 typed data and wallet information for threat analysis.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ThreatAnalysisRequestDto" + } + } + } + }, "responses": { "200": { - "description": "Paginated list of multisig transactions", + "description": "Threat analysis results including threat findings and balance changes.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/MultisigTransactionPage" + "$ref": "#/components/schemas/ThreatAnalysisResponseDto" } } } } }, - "summary": "Get multisig transactions", + "summary": "Analyze transaction threat", "tags": [ - "transactions" + "safe-shield" ] } }, - "/v1/chains/{chainId}/transactions/{safeTxHash}": { - "delete": { - "description": "Deletes a pending multisig transaction. Only the proposer or a Safe owner can delete a transaction.", - "operationId": "transactionsDeleteTransactionV1", + "/v1/chains/{chainId}/security/{safeAddress}/report-false-result": { + "post": { + "description": "Reports a FALSE_POSITIVE or FALSE_NEGATIVE Blockaid transaction scan result for review. Use the request_id from the original scan response to identify the transaction.", + "operationId": "safeShieldReportFalseResultV1", "parameters": [ { "name": "chainId", "required": true, "in": "path", - "description": "Chain ID where the transaction exists", + "description": "Chain ID where the Safe is deployed", "schema": { "example": "1", "type": "string" } }, { - "name": "safeTxHash", + "name": "safeAddress", "required": true, "in": "path", - "description": "Safe transaction hash (0x prefixed hex string)", + "description": "Safe contract address", "schema": { "type": "string" } @@ -4965,88 +5639,114 @@ ], "requestBody": { "required": true, - "description": "Signature proving authorization to delete the transaction", + "description": "Report details including event type, request_id from scan response, and details.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeleteTransactionDto" + "$ref": "#/components/schemas/ReportFalseResultRequestDto" } } } }, "responses": { - "204": { - "description": "Transaction deleted successfully" - }, - "400": { - "description": "Invalid signature or unauthorized deletion attempt" - }, - "404": { - "description": "Transaction not found" + "200": { + "description": "Report submitted successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportFalseResultResponseDto" + } + } + } } }, - "summary": "Delete transaction", + "summary": "Report false Blockaid scan result", "tags": [ - "transactions" + "safe-shield" ] } }, - "/v1/chains/{chainId}/safes/{safeAddress}/module-transactions": { + "/v1/targeted-messaging/outreaches/{outreachId}/chains/{chainId}/safes/{safeAddress}": { "get": { - "description": "Retrieves a paginated list of module transactions for a Safe. Module transactions are executed directly by enabled modules without requiring owner signatures.", - "operationId": "transactionsGetModuleTransactionsV1", + "operationId": "targetedMessagingGetTargetedSafeV1", "parameters": [ { - "name": "chainId", + "name": "outreachId", "required": true, "in": "path", - "description": "Chain ID where the Safe is deployed", "schema": { - "example": "1", - "type": "string" + "type": "number" } }, { - "name": "safeAddress", + "name": "chainId", "required": true, "in": "path", - "description": "Safe contract address (0x prefixed hex string)", "schema": { "type": "string" } }, { - "name": "to", - "required": false, - "in": "query", - "description": "Filter by recipient address (0x prefixed hex string)", + "name": "safeAddress", + "required": true, + "in": "path", "schema": { "type": "string" } - }, - { - "name": "module", - "required": false, - "in": "query", - "description": "Filter by module address that executed the transaction", + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TargetedSafe" + } + } + } + }, + "404": { + "description": "Safe not targeted." + } + }, + "tags": [ + "targeted-messaging" + ] + } + }, + "/v1/targeted-messaging/outreaches/{outreachId}/chains/{chainId}/safes/{safeAddress}/signers/{signerAddress}/submissions": { + "get": { + "operationId": "targetedMessagingGetSubmissionV1", + "parameters": [ + { + "name": "outreachId", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + }, + { + "name": "chainId", + "required": true, + "in": "path", "schema": { "type": "string" } }, { - "name": "transaction_hash", - "required": false, - "in": "query", - "description": "Filter by specific transaction hash", + "name": "safeAddress", + "required": true, + "in": "path", "schema": { "type": "string" } }, { - "name": "cursor", - "required": false, - "in": "query", - "description": "Pagination cursor for retrieving the next set of results", + "name": "signerAddress", + "required": true, + "in": "path", "schema": { "type": "string" } @@ -5054,42 +5754,51 @@ ], "responses": { "200": { - "description": "Paginated list of module transactions", + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ModuleTransactionPage" + "$ref": "#/components/schemas/Submission" } } } } }, - "summary": "Get module transactions", "tags": [ - "transactions" + "targeted-messaging" ] - } - }, - "/v1/chains/{chainId}/transactions/{safeTxHash}/confirmations": { + }, "post": { - "description": "Adds a confirmation signature to a pending multisig transaction. Once enough confirmations are collected to meet the Safe threshold, the transaction can be executed.", - "operationId": "transactionsAddConfirmationV1", + "operationId": "targetedMessagingCreateSubmissionV1", "parameters": [ + { + "name": "outreachId", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + }, { "name": "chainId", "required": true, "in": "path", - "description": "Chain ID where the Safe is deployed", "schema": { - "example": "1", "type": "string" } }, { - "name": "safeTxHash", + "name": "safeAddress", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "signerAddress", "required": true, "in": "path", - "description": "Safe transaction hash (0x prefixed hex string)", "schema": { "type": "string" } @@ -5097,43 +5806,82 @@ ], "requestBody": { "required": true, - "description": "Confirmation signature from a Safe owner proving their approval of the transaction", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AddConfirmationDto" + "$ref": "#/components/schemas/CreateSubmissionDto" } } } }, "responses": { - "200": { - "description": "Transaction details with updated confirmation status", + "201": { + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Transaction" + "$ref": "#/components/schemas/Submission" } } } + } + }, + "tags": [ + "targeted-messaging" + ] + } + }, + "/v1/chains/{chainId}/transactions/{id}": { + "get": { + "description": "Retrieves detailed information about a specific transaction by its ID, including execution status, confirmations, and decoded transaction data.", + "operationId": "transactionsGetTransactionByIdV1", + "parameters": [ + { + "name": "chainId", + "required": true, + "in": "path", + "description": "Chain ID where the transaction exists", + "schema": { + "example": "1", + "type": "string" + } }, - "400": { - "description": "Invalid signature or confirmation already exists for this owner" + { + "name": "id", + "required": true, + "in": "path", + "description": "Transaction ID (safe transaction hash or multisig transaction ID)", + "schema": { + "example": "multisig_0x1234567890123456789012345678901234567890_0x5678...", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Transaction details retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TransactionDetails" + } + } + } }, "404": { "description": "Transaction not found" } }, - "summary": "Add transaction confirmation", + "summary": "Get transaction details", "tags": [ "transactions" ] } }, - "/v1/chains/{chainId}/safes/{safeAddress}/incoming-transfers": { + "/v1/chains/{chainId}/safes/{safeAddress}/multisig-transactions": { "get": { - "description": "Retrieves a paginated list of incoming transfers to a Safe, including ETH and token transfers with optional filtering by date, value, token, and trust status.", - "operationId": "transactionsGetIncomingTransfersV1", + "description": "Retrieves a paginated list of multisig transactions for a Safe with optional filtering by execution date, recipient, value, nonce, and execution status.", + "operationId": "transactionsGetMultisigTransactionsV1", "parameters": [ { "name": "chainId", @@ -5154,15 +5902,6 @@ "type": "string" } }, - { - "name": "trusted", - "required": false, - "in": "query", - "description": "Filter by trust status (true for trusted tokens, false for untrusted)", - "schema": { - "type": "boolean" - } - }, { "name": "execution_date__gte", "required": false, @@ -5194,20 +5933,29 @@ "name": "value", "required": false, "in": "query", - "description": "Filter by transfer value in wei", + "description": "Filter by transaction value in wei", "schema": { "type": "string" } }, { - "name": "token_address", + "name": "nonce", "required": false, "in": "query", - "description": "Filter by token contract address (0x prefixed hex string for ERC-20 tokens)", + "description": "Filter by transaction nonce", "schema": { "type": "string" } }, + { + "name": "executed", + "required": false, + "in": "query", + "description": "Filter by execution status (true for executed, false for pending)", + "schema": { + "type": "boolean" + } + }, { "name": "cursor", "required": false, @@ -5220,42 +5968,42 @@ ], "responses": { "200": { - "description": "Paginated list of incoming transfers", + "description": "Paginated list of multisig transactions", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/IncomingTransferPage" + "$ref": "#/components/schemas/MultisigTransactionPage" } } } } }, - "summary": "Get incoming transfers", + "summary": "Get multisig transactions", "tags": [ "transactions" ] } }, - "/v1/chains/{chainId}/transactions/{safeAddress}/preview": { - "post": { - "description": "Simulates a transaction execution to preview its effects, including gas estimates, balance changes, and potential errors before actually proposing or executing it.", - "operationId": "transactionsPreviewTransactionV1", + "/v1/chains/{chainId}/transactions/{safeTxHash}": { + "delete": { + "description": "Deletes a pending multisig transaction. Only the proposer or a Safe owner can delete a transaction.", + "operationId": "transactionsDeleteTransactionV1", "parameters": [ { "name": "chainId", "required": true, "in": "path", - "description": "Chain ID where the Safe is deployed", + "description": "Chain ID where the transaction exists", "schema": { "example": "1", "type": "string" } }, { - "name": "safeAddress", + "name": "safeTxHash", "required": true, "in": "path", - "description": "Safe contract address (0x prefixed hex string)", + "description": "Safe transaction hash (0x prefixed hex string)", "schema": { "type": "string" } @@ -5263,43 +6011,36 @@ ], "requestBody": { "required": true, - "description": "Transaction data to preview including recipient, value, data, and operation type", + "description": "Signature proving authorization to delete the transaction", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PreviewTransactionDto" + "$ref": "#/components/schemas/DeleteTransactionDto" } } } }, "responses": { - "200": { - "description": "Transaction preview with simulation results, gas estimates, and potential effects", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TransactionPreview" - } - } - } + "204": { + "description": "Transaction deleted successfully" }, "400": { - "description": "Invalid transaction data or simulation failed" + "description": "Invalid signature or unauthorized deletion attempt" }, "404": { - "description": "Safe not found" + "description": "Transaction not found" } }, - "summary": "Preview transaction", + "summary": "Delete transaction", "tags": [ "transactions" ] } }, - "/v1/chains/{chainId}/safes/{safeAddress}/transactions/queued": { + "/v1/chains/{chainId}/safes/{safeAddress}/module-transactions": { "get": { - "description": "Retrieves a paginated list of queued (pending) transactions for a Safe that are waiting for execution, ordered by nonce.", - "operationId": "transactionsGetTransactionQueueV1", + "description": "Retrieves a paginated list of module transactions for a Safe. Module transactions are executed directly by enabled modules without requiring owner signatures.", + "operationId": "transactionsGetModuleTransactionsV1", "parameters": [ { "name": "chainId", @@ -5321,12 +6062,30 @@ } }, { - "name": "trusted", + "name": "to", "required": false, "in": "query", - "description": "Filter by trust status (true for trusted transactions, false for untrusted)", + "description": "Filter by recipient address (0x prefixed hex string)", "schema": { - "type": "boolean" + "type": "string" + } + }, + { + "name": "module", + "required": false, + "in": "query", + "description": "Filter by module address that executed the transaction", + "schema": { + "type": "string" + } + }, + { + "name": "transaction_hash", + "required": false, + "in": "query", + "description": "Filter by specific transaction hash", + "schema": { + "type": "string" } }, { @@ -5341,28 +6100,88 @@ ], "responses": { "200": { - "description": "Paginated list of queued transactions", + "description": "Paginated list of module transactions", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/QueuedItemPage" + "$ref": "#/components/schemas/ModuleTransactionPage" } } } } }, - "summary": "Get transaction queue", + "summary": "Get module transactions", "tags": [ "transactions" ] } }, - "/v1/chains/{chainId}/safes/{safeAddress}/transactions/history": { - "get": { - "description": "Retrieves a paginated list of executed transactions for a Safe, including multisig transactions, module transactions, and incoming transfers, ordered by execution date.", - "operationId": "transactionsGetTransactionsHistoryV1", - "parameters": [ - { + "/v1/chains/{chainId}/transactions/{safeTxHash}/confirmations": { + "post": { + "description": "Adds a confirmation signature to a pending multisig transaction. Once enough confirmations are collected to meet the Safe threshold, the transaction can be executed.", + "operationId": "transactionsAddConfirmationV1", + "parameters": [ + { + "name": "chainId", + "required": true, + "in": "path", + "description": "Chain ID where the Safe is deployed", + "schema": { + "example": "1", + "type": "string" + } + }, + { + "name": "safeTxHash", + "required": true, + "in": "path", + "description": "Safe transaction hash (0x prefixed hex string)", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "description": "Confirmation signature from a Safe owner proving their approval of the transaction", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AddConfirmationDto" + } + } + } + }, + "responses": { + "200": { + "description": "Transaction details with updated confirmation status", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TransactionDetails" + } + } + } + }, + "400": { + "description": "Invalid signature or confirmation already exists for this owner" + }, + "404": { + "description": "Transaction not found" + } + }, + "summary": "Add transaction confirmation", + "tags": [ + "transactions" + ] + } + }, + "/v1/chains/{chainId}/safes/{safeAddress}/incoming-transfers": { + "get": { + "description": "Retrieves a paginated list of incoming transfers to a Safe, including ETH and token transfers with optional filtering by date, value, token, and trust status.", + "operationId": "transactionsGetIncomingTransfersV1", + "parameters": [ + { "name": "chainId", "required": true, "in": "path", @@ -5382,38 +6201,55 @@ } }, { - "name": "timezone_offset", + "name": "trusted", "required": false, "in": "query", - "deprecated": true, - "description": "Deprecated: Timezone offset in milliseconds for date formatting (use timezone parameter instead)", + "description": "Filter by trust status (true for trusted tokens, false for untrusted)", + "schema": { + "type": "boolean" + } + }, + { + "name": "execution_date__gte", + "required": false, + "in": "query", + "description": "Filter by execution date greater than or equal to (ISO 8601 format)", "schema": { "type": "string" } }, { - "name": "trusted", + "name": "execution_date__lte", "required": false, "in": "query", - "description": "Filter by trust status (default: true, set to false to include untrusted transactions)", + "description": "Filter by execution date less than or equal to (ISO 8601 format)", "schema": { - "type": "boolean" + "type": "string" } }, { - "name": "imitation", + "name": "to", "required": false, "in": "query", - "description": "Include imitation transactions in results (default: true, set to false to exclude)", + "description": "Filter by recipient address (0x prefixed hex string)", "schema": { - "type": "boolean" + "type": "string" } }, { - "name": "timezone", + "name": "value", "required": false, "in": "query", - "description": "IANA timezone identifier for date formatting (e.g., \"America/New_York\")", + "description": "Filter by transfer value in wei", + "schema": { + "type": "string" + } + }, + { + "name": "token_address", + "required": false, + "in": "query", + "description": "Filter by token contract address (0x prefixed hex string for ERC-20 tokens)", "schema": { "type": "string" } @@ -5430,26 +6266,26 @@ ], "responses": { "200": { - "description": "Paginated list of historical transactions", + "description": "Paginated list of incoming transfers", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TransactionItemPage" + "$ref": "#/components/schemas/IncomingTransferPage" } } } } }, - "summary": "Get transaction history", + "summary": "Get incoming transfers", "tags": [ "transactions" ] } }, - "/v1/chains/{chainId}/transactions/{safeAddress}/propose": { + "/v1/chains/{chainId}/transactions/{safeAddress}/preview": { "post": { - "description": "Proposes a new multisig transaction for a Safe. The transaction will be pending until enough owners sign it to reach the required threshold.", - "operationId": "transactionsProposeTransactionV1", + "description": "Simulates a transaction execution to preview its effects, including gas estimates, balance changes, and potential errors before actually proposing or executing it.", + "operationId": "transactionsPreviewTransactionV1", "parameters": [ { "name": "chainId", @@ -5473,40 +6309,43 @@ ], "requestBody": { "required": true, - "description": "Transaction proposal including recipient, value, data, and initial signature", + "description": "Transaction data to preview including recipient, value, data, and operation type", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ProposeTransactionDto" + "$ref": "#/components/schemas/PreviewTransactionDto" } } } }, "responses": { "200": { - "description": "Transaction proposed successfully", + "description": "Transaction preview with simulation results, gas estimates, and potential effects", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TransactionDetails" + "$ref": "#/components/schemas/TransactionPreview" } } } }, "400": { - "description": "Invalid transaction data or signature" + "description": "Invalid transaction data or simulation failed" + }, + "404": { + "description": "Safe not found" } }, - "summary": "Propose transaction", + "summary": "Preview transaction", "tags": [ "transactions" ] } }, - "/v1/chains/{chainId}/safes/{safeAddress}/transactions/creation": { + "/v1/chains/{chainId}/safes/{safeAddress}/transactions/queued": { "get": { - "description": "Retrieves the transaction that created the Safe, including the creation timestamp, creator address, factory used, and setup data.", - "operationId": "transactionsGetCreationTransactionV1", + "description": "Retrieves a paginated list of queued (pending) transactions for a Safe that are waiting for execution, ordered by nonce.", + "operationId": "transactionsGetTransactionQueueV1", "parameters": [ { "name": "chainId", @@ -5526,38 +6365,56 @@ "schema": { "type": "string" } + }, + { + "name": "trusted", + "required": false, + "in": "query", + "description": "Filter by trust status (true for trusted transactions, false for untrusted)", + "schema": { + "type": "boolean" + } + }, + { + "name": "cursor", + "required": false, + "in": "query", + "description": "Pagination cursor for retrieving the next set of results", + "schema": { + "type": "string" + } } ], "responses": { "200": { - "description": "Safe creation transaction details", + "description": "Paginated list of queued transactions", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreationTransaction" + "$ref": "#/components/schemas/QueuedItemPage" } } } - }, - "404": { - "description": "Safe not found or creation transaction not available" } }, - "summary": "Get Safe creation transaction", + "summary": "Get transaction queue", "tags": [ "transactions" ] } }, - "/v1/export/chains/{chainId}/{safeAddress}": { - "post": { - "operationId": "csvExportLaunchExportV1", + "/v1/chains/{chainId}/safes/{safeAddress}/transactions/history": { + "get": { + "description": "Retrieves a paginated list of executed transactions for a Safe, including multisig transactions, module transactions, and incoming transfers, ordered by execution date.", + "operationId": "transactionsGetTransactionsHistoryV1", "parameters": [ { "name": "chainId", "required": true, "in": "path", + "description": "Chain ID where the Safe is deployed", "schema": { + "example": "1", "type": "string" } }, @@ -5565,54 +6422,243 @@ "name": "safeAddress", "required": true, "in": "path", + "description": "Safe contract address (0x prefixed hex string)", "schema": { "type": "string" } - } - ], - "requestBody": { - "required": false, - "description": "Transaction export request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TransactionExportDto" - } + }, + { + "name": "timezone_offset", + "required": false, + "in": "query", + "deprecated": true, + "description": "Deprecated: Timezone offset in milliseconds for date formatting (use timezone parameter instead)", + "schema": { + "type": "string" + } + }, + { + "name": "trusted", + "required": false, + "in": "query", + "description": "Filter by trust status (default: true, set to false to include untrusted transactions)", + "schema": { + "type": "boolean" + } + }, + { + "name": "imitation", + "required": false, + "in": "query", + "description": "Include imitation transactions in results (default: true, set to false to exclude)", + "schema": { + "type": "boolean" + } + }, + { + "name": "timezone", + "required": false, + "in": "query", + "description": "IANA timezone identifier for date formatting (e.g., \"America/New_York\")", + "schema": { + "type": "string" + } + }, + { + "name": "cursor", + "required": false, + "in": "query", + "description": "Pagination cursor for retrieving the next set of results", + "schema": { + "type": "string" } } - }, + ], "responses": { - "202": { - "description": "", + "200": { + "description": "Paginated list of historical transactions", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/JobStatusDto" + "$ref": "#/components/schemas/TransactionItemPage" } } } } }, + "summary": "Get transaction history", "tags": [ - "export" + "transactions" ] } }, - "/v1/export/{jobId}/status": { - "get": { - "operationId": "csvExportGetExportStatusV1", + "/v1/chains/{chainId}/transactions/{safeAddress}/propose": { + "post": { + "description": "Proposes a new multisig transaction for a Safe. The transaction will be pending until enough owners sign it to reach the required threshold.", + "operationId": "transactionsProposeTransactionV1", "parameters": [ { - "name": "jobId", + "name": "chainId", "required": true, "in": "path", + "description": "Chain ID where the Safe is deployed", "schema": { + "example": "1", "type": "string" } - } - ], - "responses": { - "200": { + }, + { + "name": "safeAddress", + "required": true, + "in": "path", + "description": "Safe contract address (0x prefixed hex string)", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "description": "Transaction proposal including recipient, value, data, and initial signature", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProposeTransactionDto" + } + } + } + }, + "responses": { + "200": { + "description": "Transaction proposed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TransactionDetails" + } + } + } + }, + "400": { + "description": "Invalid transaction data or signature" + } + }, + "summary": "Propose transaction", + "tags": [ + "transactions" + ] + } + }, + "/v1/chains/{chainId}/safes/{safeAddress}/transactions/creation": { + "get": { + "description": "Retrieves the transaction that created the Safe, including the creation timestamp, creator address, factory used, and setup data.", + "operationId": "transactionsGetCreationTransactionV1", + "parameters": [ + { + "name": "chainId", + "required": true, + "in": "path", + "description": "Chain ID where the Safe is deployed", + "schema": { + "example": "1", + "type": "string" + } + }, + { + "name": "safeAddress", + "required": true, + "in": "path", + "description": "Safe contract address (0x prefixed hex string)", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Safe creation transaction details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreationTransaction" + } + } + } + }, + "404": { + "description": "Safe not found or creation transaction not available" + } + }, + "summary": "Get Safe creation transaction", + "tags": [ + "transactions" + ] + } + }, + "/v1/export/chains/{chainId}/{safeAddress}": { + "post": { + "operationId": "csvExportLaunchExportV1", + "parameters": [ + { + "name": "chainId", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "safeAddress", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "description": "Transaction export request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TransactionExportDto" + } + } + } + }, + "responses": { + "202": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JobStatusDto" + } + } + } + } + }, + "tags": [ + "export" + ] + } + }, + "/v1/export/{jobId}/status": { + "get": { + "operationId": "csvExportGetExportStatusV1", + "parameters": [ + { + "name": "jobId", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { "description": "CSV export status retrieved successfully", "content": { "application/json": { @@ -5641,7 +6687,7 @@ "/v1/chains/{chainId}/delegates": { "get": { "deprecated": true, - "description": "Retrieves a paginated list of delegates for a specific chain. This endpoint is deprecated, please use the v2 version instead.", + "description": "Retrieves a paginated list of delegates for a specific chain. This endpoint is deprecated, please use the v3 version instead.", "operationId": "delegatesGetDelegatesV1", "parameters": [ { @@ -5719,7 +6765,7 @@ }, "post": { "deprecated": true, - "description": "Creates a new delegate for a specific chain. This endpoint is deprecated, please use the v2 version instead.", + "description": "Creates a new delegate for a specific chain. This endpoint is deprecated, please use the v3 version instead.", "operationId": "delegatesPostDelegateV1", "parameters": [ { @@ -5761,7 +6807,7 @@ "/v1/chains/{chainId}/delegates/{delegateAddress}": { "delete": { "deprecated": true, - "description": "Deletes a delegate for a specific chain and address. This endpoint is deprecated, please use the v2 version instead.", + "description": "Deletes a delegate for a specific chain and address. This endpoint is deprecated, please use the v3 version instead.", "operationId": "delegatesDeleteDelegateV1", "parameters": [ { @@ -5812,7 +6858,7 @@ "/v1/chains/{chainId}/safes/{safeAddress}/delegates/{delegateAddress}": { "delete": { "deprecated": true, - "description": "Removes a delegate from a specific Safe. This endpoint is deprecated, please use the v2 version instead.", + "description": "Removes a delegate from a specific Safe. This endpoint is deprecated, please use the v3 version instead.", "operationId": "delegatesDeleteSafeDelegateV1", "parameters": [ { @@ -5871,7 +6917,8 @@ }, "/v2/chains/{chainId}/delegates": { "get": { - "description": "Retrieves a paginated list of delegates for a specific chain with optional filtering by Safe, delegate, delegator, or label.", + "deprecated": true, + "description": "Retrieves a paginated list of delegates for a specific chain with optional filtering by Safe, delegate, delegator, or label. This endpoint is deprecated, please use the v3 version instead.", "operationId": "delegatesGetDelegatesV2", "parameters": [ { @@ -5942,13 +6989,14 @@ } } }, - "summary": "Get delegates", + "summary": "Get delegates (deprecated)", "tags": [ "delegates" ] }, "post": { - "description": "Creates a new delegate relationship between a Safe and a delegate address. Requires proper authorization signature.", + "deprecated": true, + "description": "Creates a new delegate relationship between a Safe and a delegate address. Requires proper authorization signature. This endpoint is deprecated, please use the v3 version instead.", "operationId": "delegatesPostDelegateV2", "parameters": [ { @@ -5981,7 +7029,7 @@ "description": "Invalid delegate data, signature, or unauthorized creation attempt" } }, - "summary": "Create delegate", + "summary": "Create delegate (deprecated)", "tags": [ "delegates" ] @@ -5989,7 +7037,8 @@ }, "/v2/chains/{chainId}/delegates/{delegateAddress}": { "delete": { - "description": "Removes a delegate relationship for a specific delegate address. Requires proper authorization signature.", + "deprecated": true, + "description": "Removes a delegate relationship for a specific delegate address. Requires proper authorization signature. This endpoint is deprecated, please use the v3 version instead.", "operationId": "delegatesDeleteDelegateV2", "parameters": [ { @@ -6031,202 +7080,239 @@ "description": "Invalid signature or unauthorized deletion attempt" } }, - "summary": "Delete delegate", + "summary": "Delete delegate (deprecated)", "tags": [ "delegates" ] } }, - "/v1/register/notifications": { - "post": { - "deprecated": true, - "description": "Registers a device to receive push notifications for Safe events. This endpoint is deprecated, please use the v2 version instead.", - "operationId": "notificationsRegisterDeviceV1", - "parameters": [], - "requestBody": { - "required": true, - "description": "Device registration data including device token, UUID, and Safe registrations with signatures", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RegisterDeviceDto" - } - } - } - }, - "responses": { - "200": { - "description": "Device registered successfully for notifications" - }, - "400": { - "description": "Invalid device data, expired timestamp, or invalid signature" - } - }, - "summary": "Register device for notifications (deprecated)", - "tags": [ - "notifications" - ] - } - }, - "/v1/chains/{chainId}/notifications/devices/{uuid}": { - "delete": { - "deprecated": true, - "description": "Removes a device from receiving notifications. This endpoint is deprecated, please use the v2 version instead.", - "operationId": "notificationsUnregisterDeviceV1", + "/v3/chains/{chainId}/delegates": { + "get": { + "description": "Retrieves a paginated list of delegates for a specific chain with optional filtering by Safe, delegate, delegator, or label.", + "operationId": "delegatesGetDelegatesV3", "parameters": [ { "name": "chainId", "required": true, "in": "path", - "description": "Chain ID (kept for backward compatibility)", + "description": "Chain ID where delegates are registered", "schema": { "example": "1", "type": "string" } }, { - "name": "uuid", - "required": true, - "in": "path", - "description": "Device UUID to unregister", + "name": "cursor", + "required": false, + "in": "query", + "description": "Pagination cursor for retrieving the next set of results", "schema": { - "example": "550e8400-e29b-41d4-a716-446655440000", "type": "string" } - } - ], - "responses": { - "204": { - "description": "Device unregistered successfully" - } - }, - "summary": "Unregister device (deprecated)", - "tags": [ - "notifications" - ] - } - }, - "/v1/chains/{chainId}/notifications/devices/{uuid}/safes/{safeAddress}": { - "delete": { - "deprecated": true, - "description": "Removes a specific Safe from receiving notifications on a device. This endpoint is deprecated, please use the v2 version instead.", - "operationId": "notificationsUnregisterSafeV1", - "parameters": [ + }, { - "name": "chainId", - "required": true, - "in": "path", - "description": "Chain ID where the Safe is deployed", + "name": "label", + "required": false, + "in": "query", + "description": "Filter by delegate label or name", "schema": { - "example": "1", "type": "string" } }, { - "name": "uuid", - "required": true, - "in": "path", - "description": "Device UUID", + "name": "delegator", + "required": false, + "in": "query", + "description": "Filter by delegator address (0x prefixed hex string)", "schema": { - "example": "550e8400-e29b-41d4-a716-446655440000", "type": "string" } }, { - "name": "safeAddress", - "required": true, - "in": "path", - "description": "Safe contract address (0x prefixed hex string)", + "name": "delegate", + "required": false, + "in": "query", + "description": "Filter by delegate address (0x prefixed hex string)", + "schema": { + "type": "string" + } + }, + { + "name": "safe", + "required": false, + "in": "query", + "description": "Filter by Safe address (0x prefixed hex string)", "schema": { "type": "string" } } ], "responses": { - "204": { - "description": "Safe unregistered from device notifications successfully" + "200": { + "description": "Paginated list of delegates retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DelegatePage" + } + } + } } }, - "summary": "Unregister Safe from device (deprecated)", + "summary": "Get delegates", "tags": [ - "notifications" + "delegates" ] - } - }, - "/v2/register/notifications": { + }, "post": { - "description": "Registers or updates a device to receive push notifications for Safe events. Creates subscriptions for specified Safes and notification types.", - "operationId": "notificationsUpsertSubscriptionsV2", - "parameters": [], + "description": "Creates a new delegate relationship between a Safe and a delegate address. Requires proper authorization signature.", + "operationId": "delegatesPostDelegateV3", + "parameters": [ + { + "name": "chainId", + "required": true, + "in": "path", + "description": "Chain ID where the delegate will be registered", + "schema": { + "example": "1", + "type": "string" + } + } + ], "requestBody": { "required": true, - "description": "Device and subscription data including device token, Safe addresses, and notification preferences", + "description": "Delegate creation data including Safe address, delegate address, label, and authorization signature", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpsertSubscriptionsDto" + "$ref": "#/components/schemas/CreateDelegateDto" } } } }, "responses": { - "201": { - "description": "Device registered successfully with returned device UUID", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "deviceUuid": { - "type": "string", - "format": "uuid", - "description": "Generated UUID for the registered device" - } - } - } + "204": { + "description": "Delegate created successfully" + }, + "400": { + "description": "Invalid delegate data, signature, or unauthorized creation attempt" + } + }, + "summary": "Create delegate", + "tags": [ + "delegates" + ] + }, + "patch": { + "description": "Updates an existing delegate relationship (e.g. the delegate label). Requires proper authorization signature.", + "operationId": "delegatesUpdateDelegateV3", + "parameters": [ + { + "name": "chainId", + "required": true, + "in": "path", + "description": "Chain ID where the delegate is registered", + "schema": { + "example": "1", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "description": "Delegate update data including Safe address, delegate address, delegator, label, and authorization signature", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateDelegateV3Dto" } } + } + }, + "responses": { + "204": { + "description": "Delegate updated successfully" }, "400": { - "description": "Invalid device data or subscription configuration" + "description": "Invalid delegate data, signature, or unauthorized update attempt" } }, - "summary": "Register device for notifications", + "summary": "Update delegate", "tags": [ - "notifications" + "delegates" ] } }, - "/v2/chains/{chainId}/notifications/devices/{deviceUuid}/safes/{safeAddress}": { - "get": { - "description": "Retrieves the notification types that a device is subscribed to for a specific Safe.", - "operationId": "notificationsGetSafeSubscriptionV2", + "/v3/chains/{chainId}/delegates/{delegateAddress}": { + "delete": { + "description": "Removes a delegate relationship for a specific delegate address. Requires proper authorization signature.", + "operationId": "delegatesDeleteDelegateV3", "parameters": [ { - "name": "deviceUuid", + "name": "chainId", "required": true, "in": "path", - "description": "Device UUID", + "description": "Chain ID where the delegate is registered", + "schema": { + "example": "1", + "type": "string" + } + }, + { + "name": "delegateAddress", + "required": true, + "in": "path", + "description": "Delegate address to remove (0x prefixed hex string)", "schema": { - "example": "550e8400-e29b-41d4-a716-446655440000", "type": "string" } + } + ], + "requestBody": { + "required": true, + "description": "Signature and data proving authorization to delete the delegate", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteDelegateV3Dto" + } + } + } + }, + "responses": { + "204": { + "description": "Delegate deleted successfully" }, + "400": { + "description": "Invalid signature or unauthorized deletion attempt" + } + }, + "summary": "Delete delegate", + "tags": [ + "delegates" + ] + } + }, + "/v1/chains/{chainId}/tokens/{address}": { + "get": { + "description": "Symbol, name, decimals, logo and trust flag of a token on the given chain, as known by the Transaction Service.", + "operationId": "tokensGetTokenV1", + "parameters": [ { "name": "chainId", "required": true, "in": "path", - "description": "Chain ID where the Safe is deployed", + "description": "Chain ID the token is deployed on", "schema": { "example": "1", "type": "string" } }, { - "name": "safeAddress", + "name": "address", "required": true, "in": "path", - "description": "Safe contract address (0x prefixed hex string)", + "description": "Token contract address (0x prefixed hex string)", "schema": { "type": "string" } @@ -6234,111 +7320,140 @@ ], "responses": { "200": { - "description": "List of notification types the device is subscribed to for this Safe", + "description": "Token metadata", "content": { "application/json": { "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/NotificationTypeResponseDto" - } + "oneOf": [ + { + "$ref": "#/components/schemas/NativeTokenMetadata" + }, + { + "$ref": "#/components/schemas/Erc20TokenMetadata" + }, + { + "$ref": "#/components/schemas/Erc721TokenMetadata" + } + ] } } } }, - "401": { - "description": "Authentication required - valid JWT token must be provided" - }, "404": { - "description": "Device, Safe, or subscription not found" + "description": "The Transaction Service does not know this token" + }, + "422": { + "description": "Invalid chain ID or address" + }, + "429": { + "description": "Rate limit exceeded" } }, - "summary": "Get Safe subscription", + "summary": "Get token metadata", "tags": [ - "notifications" + "tokens" ] - }, - "delete": { - "description": "Removes all notification subscriptions for a specific Safe on a device.", - "operationId": "notificationsDeleteSubscriptionV2", + } + }, + "/v1/chains/{chainId}/tokens": { + "get": { + "description": "Metadata for up to 20 tokens of one chain, in request order. Addresses the Transaction Service does not know are omitted.", + "operationId": "tokensGetTokensV1", "parameters": [ - { - "name": "deviceUuid", - "required": true, - "in": "path", - "description": "Device UUID", - "schema": { - "example": "550e8400-e29b-41d4-a716-446655440000", - "type": "string" - } - }, { "name": "chainId", "required": true, "in": "path", - "description": "Chain ID where the Safe is deployed", + "description": "Chain ID the token is deployed on", "schema": { "example": "1", "type": "string" } }, { - "name": "safeAddress", + "name": "addresses", "required": true, - "in": "path", - "description": "Safe contract address (0x prefixed hex string)", + "in": "query", + "description": "Comma-separated token contract addresses, at most 20", "schema": { + "example": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48,0xdAC17F958D2ee523a2206206994597C13D831ec7", "type": "string" } } ], "responses": { - "204": { - "description": "Safe subscription deleted successfully" + "200": { + "description": "Token metadata for the known addresses, in request order", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/NativeTokenMetadata" + }, + { + "$ref": "#/components/schemas/Erc20TokenMetadata" + }, + { + "$ref": "#/components/schemas/Erc721TokenMetadata" + } + ] + } + } + } + } }, - "404": { - "description": "Device, Safe, or subscription not found" + "422": { + "description": "Invalid chain ID, malformed address, empty list or more than 20 addresses" + }, + "429": { + "description": "Rate limit exceeded" } }, - "summary": "Delete Safe subscription", + "summary": "Get metadata for several tokens", "tags": [ - "notifications" + "tokens" ] } }, - "/v2/notifications/subscriptions": { - "delete": { - "description": "Delete all subscriptions of a Safe on a device. This will delete all subscriptions of a Safe on a device for all chains passed in the request body.", - "operationId": "notificationsDeleteAllSubscriptionsV2", + "/v1/register/notifications": { + "post": { + "deprecated": true, + "description": "Registers a device to receive push notifications for Safe events. This endpoint is deprecated, please use the v2 version instead.", + "operationId": "notificationsRegisterDeviceV1", "parameters": [], "requestBody": { "required": true, + "description": "Device registration data including device token, UUID, and Safe registrations with signatures", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeleteAllSubscriptionsDto" + "$ref": "#/components/schemas/RegisterDeviceDto" } } } }, "responses": { - "404": { - "description": "No subscription was found" + "200": { + "description": "Device registered successfully for notifications" }, - "422": { - "description": "The request body is invalid" + "400": { + "description": "Invalid device data, expired timestamp, or invalid signature" } }, - "summary": "Delete all subscriptions of a device", + "summary": "Register device for notifications (deprecated)", "tags": [ "notifications" ] } }, - "/v2/chains/{chainId}/notifications/devices/{deviceUuid}": { + "/v1/chains/{chainId}/notifications/devices/{uuid}": { "delete": { - "description": "Removes a device and all its notification subscriptions from the system.", - "operationId": "notificationsDeleteDeviceV2", + "deprecated": true, + "description": "Removes a device from receiving notifications. This endpoint is deprecated, please use the v2 version instead.", + "operationId": "notificationsUnregisterDeviceV1", "parameters": [ { "name": "chainId", @@ -6351,10 +7466,10 @@ } }, { - "name": "deviceUuid", + "name": "uuid", "required": true, "in": "path", - "description": "Device UUID to delete", + "description": "Device UUID to unregister", "schema": { "example": "550e8400-e29b-41d4-a716-446655440000", "type": "string" @@ -6363,13 +7478,279 @@ ], "responses": { "204": { - "description": "Device deleted successfully" - }, - "404": { - "description": "Device not found" + "description": "Device unregistered successfully" } }, - "summary": "Delete device", + "summary": "Unregister device (deprecated)", + "tags": [ + "notifications" + ] + } + }, + "/v1/chains/{chainId}/notifications/devices/{uuid}/safes/{safeAddress}": { + "delete": { + "deprecated": true, + "description": "Removes a specific Safe from receiving notifications on a device. This endpoint is deprecated, please use the v2 version instead.", + "operationId": "notificationsUnregisterSafeV1", + "parameters": [ + { + "name": "chainId", + "required": true, + "in": "path", + "description": "Chain ID where the Safe is deployed", + "schema": { + "example": "1", + "type": "string" + } + }, + { + "name": "uuid", + "required": true, + "in": "path", + "description": "Device UUID", + "schema": { + "example": "550e8400-e29b-41d4-a716-446655440000", + "type": "string" + } + }, + { + "name": "safeAddress", + "required": true, + "in": "path", + "description": "Safe contract address (0x prefixed hex string)", + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "Safe unregistered from device notifications successfully" + } + }, + "summary": "Unregister Safe from device (deprecated)", + "tags": [ + "notifications" + ] + } + }, + "/v2/register/notifications": { + "post": { + "description": "Registers or updates a device to receive push notifications for Safe events. Creates subscriptions for specified Safes and notification types.", + "operationId": "notificationsUpsertSubscriptionsV2", + "parameters": [], + "requestBody": { + "required": true, + "description": "Device and subscription data including device token, Safe addresses, and notification preferences", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpsertSubscriptionsDto" + } + } + } + }, + "responses": { + "201": { + "description": "Device registered successfully with returned device UUID", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "deviceUuid": { + "type": "string", + "format": "uuid", + "description": "Generated UUID for the registered device" + } + } + } + } + } + }, + "400": { + "description": "Invalid device data or subscription configuration" + } + }, + "summary": "Register device for notifications", + "tags": [ + "notifications" + ] + } + }, + "/v2/chains/{chainId}/notifications/devices/{deviceUuid}/safes/{safeAddress}": { + "get": { + "description": "Retrieves the notification types that a device is subscribed to for a specific Safe.", + "operationId": "notificationsGetSafeSubscriptionV2", + "parameters": [ + { + "name": "deviceUuid", + "required": true, + "in": "path", + "description": "Device UUID", + "schema": { + "example": "550e8400-e29b-41d4-a716-446655440000", + "type": "string" + } + }, + { + "name": "chainId", + "required": true, + "in": "path", + "description": "Chain ID where the Safe is deployed", + "schema": { + "example": "1", + "type": "string" + } + }, + { + "name": "safeAddress", + "required": true, + "in": "path", + "description": "Safe contract address (0x prefixed hex string)", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "List of notification types the device is subscribed to for this Safe", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/NotificationTypeResponseDto" + } + } + } + } + }, + "401": { + "description": "Authentication required - valid JWT token must be provided" + }, + "404": { + "description": "Device, Safe, or subscription not found" + } + }, + "summary": "Get Safe subscription", + "tags": [ + "notifications" + ] + }, + "delete": { + "description": "Removes all notification subscriptions for a specific Safe on a device.", + "operationId": "notificationsDeleteSubscriptionV2", + "parameters": [ + { + "name": "deviceUuid", + "required": true, + "in": "path", + "description": "Device UUID", + "schema": { + "example": "550e8400-e29b-41d4-a716-446655440000", + "type": "string" + } + }, + { + "name": "chainId", + "required": true, + "in": "path", + "description": "Chain ID where the Safe is deployed", + "schema": { + "example": "1", + "type": "string" + } + }, + { + "name": "safeAddress", + "required": true, + "in": "path", + "description": "Safe contract address (0x prefixed hex string)", + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "Safe subscription deleted successfully" + }, + "404": { + "description": "Device, Safe, or subscription not found" + } + }, + "summary": "Delete Safe subscription", + "tags": [ + "notifications" + ] + } + }, + "/v2/notifications/subscriptions": { + "delete": { + "description": "Delete all subscriptions of a Safe on a device. This will delete all subscriptions of a Safe on a device for all chains passed in the request body.", + "operationId": "notificationsDeleteAllSubscriptionsV2", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteAllSubscriptionsDto" + } + } + } + }, + "responses": { + "404": { + "description": "No subscription was found" + }, + "422": { + "description": "The request body is invalid" + } + }, + "summary": "Delete all subscriptions of a device", + "tags": [ + "notifications" + ] + } + }, + "/v2/chains/{chainId}/notifications/devices/{deviceUuid}": { + "delete": { + "description": "Removes a device and all its notification subscriptions from the system.", + "operationId": "notificationsDeleteDeviceV2", + "parameters": [ + { + "name": "chainId", + "required": true, + "in": "path", + "description": "Chain ID (kept for backward compatibility)", + "schema": { + "example": "1", + "type": "string" + } + }, + { + "name": "deviceUuid", + "required": true, + "in": "path", + "description": "Device UUID to delete", + "schema": { + "example": "550e8400-e29b-41d4-a716-446655440000", + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "Device deleted successfully" + }, + "404": { + "description": "Device not found" + } + }, + "summary": "Delete device", "tags": [ "notifications" ] @@ -6379,7 +7760,7 @@ "info": { "title": "Safe Client Gateway", "description": "", - "version": "main", + "version": "main-f5e1d80", "contact": {} }, "tags": [], @@ -6390,114 +7771,1294 @@ "type": "object", "properties": { "name": { - "type": "string" + "type": "string" + }, + "version": { + "type": "string", + "nullable": true + }, + "buildNumber": { + "type": "string", + "nullable": true + } + }, + "required": [ + "name" + ] + }, + "UserSession": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "authMethod": { + "type": "string", + "enum": [ + "siwe", + "oidc" + ] + }, + "signerAddress": { + "type": "string", + "description": "Wallet signer address. Present only for SIWE-authenticated users." + }, + "email": { + "type": "string", + "description": "Verified email address. Present only for OIDC-authenticated users when stored." + } + }, + "required": [ + "id", + "authMethod" + ] + }, + "AuthNonce": { + "type": "object", + "properties": { + "nonce": { + "type": "string" + } + }, + "required": [ + "nonce" + ] + }, + "SiweDto": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "signature": { + "type": "string" + } + }, + "required": [ + "message", + "signature" + ] + }, + "LogoutDto": { + "type": "object", + "properties": { + "redirect_url": { + "type": "string", + "description": "Post-logout redirect URL (must be same-origin as pre-configured URL)" + } + } + }, + "Authenticator": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Auth0 authentication method identifier (e.g. totp|...)" + }, + "type": { + "type": "string", + "description": "Authentication method type (e.g. totp)" + }, + "name": { + "type": "string", + "description": "User-visible authenticator name" + }, + "createdAt": { + "type": "string", + "description": "ISO 8601 timestamp of when the method was enrolled" + } + }, + "required": [ + "id", + "type" + ] + }, + "NativeToken": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "decimals": { + "type": "number" + }, + "logoUri": { + "type": "string" + }, + "name": { + "type": "string" + }, + "symbol": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "NATIVE_TOKEN" + ] + } + }, + "required": [ + "address", + "decimals", + "logoUri", + "name", + "symbol", + "type" + ] + }, + "Erc20Token": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "decimals": { + "type": "number" + }, + "logoUri": { + "type": "string" + }, + "name": { + "type": "string" + }, + "symbol": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "ERC20" + ] + } + }, + "required": [ + "address", + "decimals", + "logoUri", + "name", + "symbol", + "type" + ] + }, + "Erc721Token": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "decimals": { + "type": "number" + }, + "logoUri": { + "type": "string" + }, + "name": { + "type": "string" + }, + "symbol": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "ERC721" + ] + } + }, + "required": [ + "address", + "decimals", + "logoUri", + "name", + "symbol", + "type" + ] + }, + "Balance": { + "type": "object", + "properties": { + "balance": { + "type": "string" + }, + "fiatBalance": { + "type": "string" + }, + "fiatConversion": { + "type": "string" + }, + "tokenInfo": { + "oneOf": [ + { + "$ref": "#/components/schemas/NativeToken" + }, + { + "$ref": "#/components/schemas/Erc20Token" + }, + { + "$ref": "#/components/schemas/Erc721Token" + } + ] + }, + "fiatBalance24hChange": { + "type": "string", + "nullable": true + } + }, + "required": [ + "balance", + "fiatBalance", + "fiatConversion", + "tokenInfo" + ] + }, + "Balances": { + "type": "object", + "properties": { + "fiatTotal": { + "type": "string" + }, + "items": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/Balance" + } + ] + } + } + }, + "required": [ + "fiatTotal", + "items" + ] + }, + "SubscriptionPlan": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string", + "nullable": true + }, + "description": { + "type": "string", + "nullable": true + }, + "currentPrice": { + "type": "number" + }, + "originalPrice": { + "type": "number", + "nullable": true + }, + "paymentMethod": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "features": { + "type": "array", + "items": { + "type": "string" + } + }, + "billingCycle": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string" + }, + "product": { + "type": "string", + "nullable": true + } + }, + "required": [ + "id", + "currentPrice", + "originalPrice", + "paymentMethod", + "currency", + "features", + "type", + "product" + ] + }, + "Subscription": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "customerId": { + "type": "string" + }, + "upstreamCustomerId": { + "type": "string" + }, + "plan": { + "$ref": "#/components/schemas/SubscriptionPlan" + }, + "status": { + "type": "string", + "enum": [ + "active", + "canceled", + "incomplete", + "incomplete_expired", + "past_due", + "paused", + "trialing", + "unpaid" + ] + }, + "createdAt": { + "type": "number" + }, + "startAt": { + "type": "number" + }, + "cancelledAt": { + "type": "number", + "nullable": true + }, + "cancelAt": { + "type": "number", + "nullable": true + }, + "currentPeriodStart": { + "type": "number", + "nullable": true + }, + "currentPeriodEnd": { + "type": "number", + "nullable": true + }, + "metadata": { + "type": "object", + "nullable": true + }, + "hasPaymentMethod": { + "type": "boolean", + "description": "Whether the subscription has a default payment method, or its customer does as a fallback" + } + }, + "required": [ + "id", + "customerId", + "upstreamCustomerId", + "plan", + "status", + "createdAt", + "startAt", + "cancelledAt", + "cancelAt" + ] + }, + "MarketingFeature": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "Product": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "active": { + "type": "boolean" + }, + "description": { + "type": "string" + }, + "marketingFeatures": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MarketingFeature" + } + }, + "metadata": { + "type": "object" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "active", + "description", + "marketingFeatures", + "metadata", + "name" + ] + }, + "Plan": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string", + "nullable": true + }, + "description": { + "type": "string", + "nullable": true + }, + "currentPrice": { + "type": "number" + }, + "originalPrice": { + "type": "number", + "nullable": true + }, + "paymentMethod": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "features": { + "type": "array", + "items": { + "type": "string" + } + }, + "billingCycle": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string" + }, + "product": { + "$ref": "#/components/schemas/Product" + } + }, + "required": [ + "id", + "currentPrice", + "originalPrice", + "paymentMethod", + "currency", + "features", + "type", + "product" + ] + }, + "UrlResponse": { + "type": "object", + "properties": { + "url": { + "type": "string" + } + }, + "required": [ + "url" + ] + }, + "PaymentLink": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "active": { + "type": "boolean" + }, + "metadata": { + "type": "object" + }, + "customText": { + "type": "object" + }, + "afterCompletion": { + "type": "object" + }, + "lineItems": { + "type": "array", + "items": { + "type": "object" + } + }, + "trialPeriodDays": { + "type": "number", + "nullable": true + } + }, + "required": [ + "id", + "active", + "metadata" + ] + }, + "CheckoutSessionResult": { + "type": "object", + "properties": { + "sessionId": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "required": [ + "sessionId", + "url" + ] + }, + "PreviewLineItem": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "amount": { + "type": "number", + "description": "Signed amount in minor units; negative for credit on unused time" + }, + "currency": { + "type": "string" + } + }, + "required": [ + "description", + "amount", + "currency" + ] + }, + "SubscriptionUpdatePreview": { + "type": "object", + "properties": { + "amountDue": { + "type": "number" + }, + "currency": { + "type": "string" + }, + "nextBillingDate": { + "type": "number", + "description": "Unix timestamp in seconds" + }, + "lineItems": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PreviewLineItem" + } + } + }, + "required": [ + "amountDue", + "currency", + "nextBillingDate", + "lineItems" + ] + }, + "RemovedSafeDto": { + "type": "object", + "properties": { + "chainId": { + "type": "string" + }, + "address": { + "type": "string" + } + }, + "required": [ + "chainId", + "address" + ] + }, + "UpdateSubscriptionDto": { + "type": "object", + "properties": { + "planId": { + "type": "string", + "description": "The price id of the plan to move the subscription onto" + }, + "paymentLinkId": { + "type": "string", + "description": "Which offered payment link sells that plan. Only needed to disambiguate when several do" + }, + "removedSafes": { + "description": "Safes to remove from the workspace before the plan changes, so it fits the new plan. Safes the workspace does not hold are ignored", + "type": "array", + "items": { + "$ref": "#/components/schemas/RemovedSafeDto" + } + } + }, + "required": [ + "planId" + ] + }, + "UpdateSubscriptionResult": { + "type": "object", + "properties": { + "subscriptionId": { + "type": "string" + }, + "success": { + "type": "boolean" + } + }, + "required": [ + "subscriptionId", + "success" + ] + }, + "CheckoutSession": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "object": { + "type": "string" + }, + "amountSubtotal": { + "type": "number" + }, + "amountTotal": { + "type": "number" + }, + "cancelUrl": { + "type": "string" + }, + "clientReferenceId": { + "type": "object", + "nullable": true + }, + "created": { + "type": "number" + }, + "currency": { + "type": "string" + }, + "customer": { + "type": "object", + "nullable": true + }, + "expiresAt": { + "type": "number" + }, + "metadata": { + "type": "object" + }, + "mode": { + "type": "string" + }, + "paymentStatus": { + "type": "string" + }, + "status": { + "type": "string" + }, + "successUrl": { + "type": "string" + }, + "url": { + "type": "object", + "nullable": true + }, + "subscription": { + "type": "object", + "nullable": true + }, + "invoice": { + "type": "object", + "nullable": true + } + }, + "required": [ + "id", + "object", + "amountSubtotal", + "amountTotal", + "cancelUrl", + "created", + "currency", + "expiresAt", + "metadata", + "mode", + "paymentStatus", + "status", + "successUrl" + ] + }, + "Position": { + "type": "object", + "properties": { + "balance": { + "type": "string" + }, + "fiatBalance": { + "type": "string" + }, + "fiatConversion": { + "type": "string" + }, + "tokenInfo": { + "oneOf": [ + { + "$ref": "#/components/schemas/NativeToken" + }, + { + "$ref": "#/components/schemas/Erc20Token" + }, + { + "$ref": "#/components/schemas/Erc721Token" + } + ] + }, + "fiatBalance24hChange": { + "type": "string", + "nullable": true + }, + "position_type": { + "type": "string", + "enum": [ + "deposit", + "loan", + "locked", + "staked", + "reward", + "wallet", + "airdrop", + "margin", + "unknown" + ], + "nullable": true + } + }, + "required": [ + "balance", + "fiatBalance", + "fiatConversion", + "tokenInfo", + "fiatBalance24hChange", + "position_type" + ] + }, + "PositionGroup": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "items": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/Position" + } + ] + } + } + }, + "required": [ + "name", + "items" + ] + }, + "ProtocolIcon": { + "type": "object", + "properties": { + "url": { + "type": "string", + "nullable": true + } + }, + "required": [ + "url" + ] + }, + "ProtocolMetadata": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "icon": { + "$ref": "#/components/schemas/ProtocolIcon" + } + }, + "required": [ + "name", + "icon" + ] + }, + "Protocol": { + "type": "object", + "properties": { + "protocol": { + "type": "string" + }, + "protocol_metadata": { + "$ref": "#/components/schemas/ProtocolMetadata" + }, + "fiatTotal": { + "type": "string" + }, + "items": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/PositionGroup" + } + ] + } + } + }, + "required": [ + "protocol", + "protocol_metadata", + "fiatTotal", + "items" + ] + }, + "PortfolioNativeToken": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "decimals": { + "type": "number" + }, + "logoUri": { + "type": "string" + }, + "name": { + "type": "string" + }, + "symbol": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "NATIVE_TOKEN" + ] + }, + "chainId": { + "type": "string", + "description": "The chain ID" + }, + "trusted": { + "type": "boolean", + "description": "Whether the token is trusted (spam filter)" + } + }, + "required": [ + "address", + "decimals", + "logoUri", + "name", + "symbol", + "type", + "chainId", + "trusted" + ] + }, + "PortfolioErc20Token": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "decimals": { + "type": "number" + }, + "logoUri": { + "type": "string" + }, + "name": { + "type": "string" + }, + "symbol": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "ERC20" + ] + }, + "chainId": { + "type": "string", + "description": "The chain ID" + }, + "trusted": { + "type": "boolean", + "description": "Whether the token is trusted (spam filter)" + } + }, + "required": [ + "address", + "decimals", + "logoUri", + "name", + "symbol", + "type", + "chainId", + "trusted" + ] + }, + "PortfolioErc721Token": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "decimals": { + "type": "number" + }, + "logoUri": { + "type": "string" + }, + "name": { + "type": "string" + }, + "symbol": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "ERC721" + ] + }, + "chainId": { + "type": "string", + "description": "The chain ID" + }, + "trusted": { + "type": "boolean", + "description": "Whether the token is trusted (spam filter)" + } + }, + "required": [ + "address", + "decimals", + "logoUri", + "name", + "symbol", + "type", + "chainId", + "trusted" + ] + }, + "TokenBalance": { + "type": "object", + "properties": { + "tokenInfo": { + "description": "Token information", + "oneOf": [ + { + "$ref": "#/components/schemas/PortfolioNativeToken" + }, + { + "$ref": "#/components/schemas/PortfolioErc20Token" + }, + { + "$ref": "#/components/schemas/PortfolioErc721Token" + } + ] + }, + "balance": { + "type": "string", + "description": "Balance in smallest unit as string integer. Use decimals to convert." + }, + "balanceFiat": { + "type": "string", + "description": "Balance in requested fiat currency. Decimal string without exponent notation or thousand separators.", + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "example": "4801.653401839" + }, + "price": { + "type": "string", + "description": "Token price in requested fiat currency. Decimal string without exponent notation or thousand separators.", + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "example": "3890.12" + }, + "priceChangePercentage1d": { + "type": "string", + "description": "Price change as decimal (e.g., \"-0.0431\" for -4.31%). Decimal string without exponent notation.", + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "example": "-0.0431" + } + }, + "required": [ + "tokenInfo", + "balance" + ] + }, + "AppPosition": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Unique position key" + }, + "type": { + "type": "string", + "description": "Position type (e.g., staked, lending, liquidity)" + }, + "name": { + "type": "string", + "description": "Position name" + }, + "groupId": { + "type": "string", + "description": "Group ID for grouping related positions together" + }, + "tokenInfo": { + "description": "Token information", + "oneOf": [ + { + "$ref": "#/components/schemas/PortfolioNativeToken" + }, + { + "$ref": "#/components/schemas/PortfolioErc20Token" + }, + { + "$ref": "#/components/schemas/PortfolioErc721Token" + } + ] + }, + "receiptTokenAddress": { + "type": "string", + "description": "Receipt token address (pool address) representing this position. This is the contract address for the position token (LP token, staking receipt, etc.), not the underlying token." + }, + "balance": { + "type": "string", + "description": "Balance in smallest unit as string integer. Use decimals to convert." + }, + "balanceFiat": { + "type": "string", + "description": "Balance in requested fiat currency. Decimal string without exponent notation or thousand separators.", + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "example": "18638914.125656575" + }, + "priceChangePercentage1d": { + "type": "string", + "description": "Price change as decimal (e.g., \"-0.0431\" for -4.31%). Decimal string without exponent notation.", + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "example": "-0.0431" + } + }, + "required": [ + "key", + "type", + "name", + "tokenInfo", + "balance" + ] + }, + "AppPositionGroup": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Group name (e.g., \"Protocol A Vesting\")" }, - "version": { + "items": { + "type": "array", + "description": "Positions in this group", + "items": { + "$ref": "#/components/schemas/AppPosition" + } + } + }, + "required": [ + "name", + "items" + ] + }, + "AppBalanceAppInfo": { + "type": "object", + "properties": { + "name": { "type": "string", - "nullable": true + "description": "Application name" }, - "buildNumber": { + "logoUrl": { "type": "string", - "nullable": true + "format": "uri", + "description": "Application logo URL (HTTPS)" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Application URL (HTTPS)" } }, "required": [ "name" ] }, - "UserSession": { + "AppBalance": { "type": "object", "properties": { - "id": { - "type": "string" - }, - "authMethod": { - "type": "string", - "enum": [ - "siwe", - "oidc" + "appInfo": { + "description": "Application information", + "allOf": [ + { + "$ref": "#/components/schemas/AppBalanceAppInfo" + } ] }, - "signerAddress": { + "balanceFiat": { "type": "string", - "description": "Wallet signer address. Present only for SIWE-authenticated users." + "description": "Total balance in fiat currency across all position groups. Decimal string without exponent notation or thousand separators.", + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "example": "18638914.125656575" }, - "email": { - "type": "string", - "description": "Verified email address. Present only for OIDC-authenticated users when stored." + "groups": { + "type": "array", + "description": "Position groups in this app, grouped by position name", + "items": { + "$ref": "#/components/schemas/AppPositionGroup" + } } }, "required": [ - "id", - "authMethod" + "appInfo", + "balanceFiat", + "groups" ] }, - "AuthNonce": { + "Portfolio": { "type": "object", "properties": { - "nonce": { - "type": "string" + "totalBalanceFiat": { + "type": "string", + "description": "Total balance in fiat currency across all tokens and positions. Decimal string without exponent notation or thousand separators.", + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "example": "954181237.094243" + }, + "totalTokenBalanceFiat": { + "type": "string", + "description": "Total balance in fiat currency for all token holdings. Decimal string without exponent notation or thousand separators.", + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "example": "935542322.9685864" + }, + "totalPositionsBalanceFiat": { + "type": "string", + "description": "Total balance in fiat currency for all app positions. Decimal string without exponent notation or thousand separators.", + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "example": "18638914.125656575" + }, + "tokenBalances": { + "description": "List of token balances", + "type": "array", + "items": { + "$ref": "#/components/schemas/TokenBalance" + } + }, + "positionBalances": { + "description": "List of app balances", + "type": "array", + "items": { + "$ref": "#/components/schemas/AppBalance" + } } }, "required": [ - "nonce" + "totalBalanceFiat", + "totalTokenBalanceFiat", + "totalPositionsBalanceFiat", + "tokenBalances", + "positionBalances" ] }, - "SiweDto": { + "GasPriceOracle": { "type": "object", "properties": { - "message": { + "type": { + "type": "string", + "enum": [ + "oracle" + ] + }, + "gasParameter": { "type": "string" }, - "signature": { + "gweiFactor": { + "type": "string" + }, + "uri": { "type": "string" } }, "required": [ - "message", - "signature" + "type", + "gasParameter", + "gweiFactor", + "uri" ] }, - "LogoutDto": { + "GasPriceFixed": { "type": "object", "properties": { - "redirect_url": { + "type": { "type": "string", - "description": "Post-logout redirect URL (must be same-origin as pre-configured URL)" + "enum": [ + "fixed" + ] + }, + "weiValue": { + "type": "string" } - } + }, + "required": [ + "type", + "weiValue" + ] }, - "Authenticator": { + "GasPriceFixedEIP1559": { "type": "object", "properties": { - "id": { - "type": "string", - "description": "Auth0 authentication method identifier (e.g. totp|...)" - }, "type": { "type": "string", - "description": "Authentication method type (e.g. totp)" + "enum": [ + "fixed1559" + ] }, - "name": { - "type": "string", - "description": "User-visible authenticator name" + "maxFeePerGas": { + "type": "string" }, - "createdAt": { - "type": "string", - "description": "ISO 8601 timestamp of when the method was enrolled" + "maxPriorityFeePerGas": { + "type": "string" } }, "required": [ - "id", - "type" + "type", + "maxFeePerGas", + "maxPriorityFeePerGas" ] }, - "NativeToken": { + "NativeCurrency": { "type": "object", "properties": { - "address": { - "type": "string" - }, "decimals": { "type": "number" }, @@ -6509,183 +9070,180 @@ }, "symbol": { "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "NATIVE_TOKEN" - ] } }, "required": [ - "address", "decimals", "logoUri", "name", - "symbol", - "type" + "symbol" ] }, - "Erc20Token": { + "BlockExplorerUriTemplate": { "type": "object", "properties": { "address": { "type": "string" }, - "decimals": { - "type": "number" - }, - "logoUri": { - "type": "string" - }, - "name": { + "api": { "type": "string" }, - "symbol": { + "txHash": { "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "ERC20" - ] } }, "required": [ "address", - "decimals", - "logoUri", - "name", - "symbol", - "type" + "api", + "txHash" ] }, - "Erc721Token": { + "BalancesProvider": { "type": "object", "properties": { - "address": { - "type": "string" - }, - "decimals": { - "type": "number" - }, - "logoUri": { - "type": "string" - }, - "name": { - "type": "string" - }, - "symbol": { - "type": "string" + "chainName": { + "type": "string", + "nullable": true }, - "type": { + "enabled": { + "type": "boolean" + } + }, + "required": [ + "chainName", + "enabled" + ] + }, + "RpcUri": { + "type": "object", + "properties": { + "authentication": { "type": "string", "enum": [ - "ERC721" + "API_KEY_PATH", + "NO_AUTHENTICATION", + "UNKNOWN" ] + }, + "value": { + "type": "string" } }, "required": [ - "address", - "decimals", - "logoUri", - "name", - "symbol", - "type" + "authentication", + "value" ] }, - "Balance": { + "Theme": { "type": "object", "properties": { - "balance": { - "type": "string" - }, - "fiatBalance": { + "backgroundColor": { "type": "string" }, - "fiatConversion": { + "textColor": { "type": "string" - }, - "tokenInfo": { - "oneOf": [ - { - "$ref": "#/components/schemas/NativeToken" - }, - { - "$ref": "#/components/schemas/Erc20Token" - }, - { - "$ref": "#/components/schemas/Erc721Token" - } - ] - }, - "fiatBalance24hChange": { - "type": "string", - "nullable": true } }, "required": [ - "balance", - "fiatBalance", - "fiatConversion", - "tokenInfo" + "backgroundColor", + "textColor" ] }, - "Balances": { + "Relayer": { "type": "object", "properties": { - "fiatTotal": { - "type": "string" + "type": { + "type": "string", + "enum": [ + "GTF", + "RELAY_FEE", + "DAILY_LIMIT", + "NO_FEE_CAMPAIGN" + ], + "nullable": true }, - "items": { + "safeCreationSponsored": { + "type": "boolean" + }, + "safeTransactionSponsored": { + "type": "boolean", + "deprecated": true, + "description": "Use gasPaymentOptions instead." + }, + "enableTenderlySimulationBeforeRelay": { + "type": "boolean" + }, + "gasPaymentOptions": { "type": "array", + "description": "Who may pay for a relayed transaction on this chain.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/Balance" - } + "type": "string", + "enum": [ + "FREE_DAILY_LIMIT", + "SUBSCRIPTION", + "PAY_FROM_SAFE", + "NO_FEE_CAMPAIGN" ] } } }, "required": [ - "fiatTotal", - "items" + "type", + "safeCreationSponsored", + "safeTransactionSponsored", + "enableTenderlySimulationBeforeRelay", + "gasPaymentOptions" ] }, - "SubscriptionPlan": { + "Chain": { "type": "object", "properties": { - "id": { + "chainId": { "type": "string" }, - "name": { - "type": "string", - "nullable": true + "chainName": { + "type": "string" }, "description": { + "type": "string" + }, + "chainLogoUri": { "type": "string", "nullable": true }, - "currentPrice": { - "type": "number" + "l2": { + "type": "boolean" }, - "originalPrice": { - "type": "number", - "nullable": true + "isTestnet": { + "type": "boolean" }, - "paymentMethod": { - "type": "string", - "enum": [ - "fiat" - ] + "zk": { + "type": "boolean" }, - "currency": { + "nativeCurrency": { + "$ref": "#/components/schemas/NativeCurrency" + }, + "transactionService": { + "type": "string" + }, + "blockExplorerUriTemplate": { + "$ref": "#/components/schemas/BlockExplorerUriTemplate" + }, + "beaconChainExplorerUriTemplate": { + "type": "object" + }, + "disabledWallets": { + "type": "array", + "items": { + "type": "string" + } + }, + "ensRegistryAddress": { "type": "string", - "enum": [ - "usd", - "eur" - ] + "nullable": true + }, + "balancesProvider": { + "$ref": "#/components/schemas/BalancesProvider" }, "features": { "type": "array", @@ -6693,1432 +9251,1660 @@ "type": "string" } }, - "billingCycle": { + "gasPrice": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/GasPriceOracle" + }, + { + "$ref": "#/components/schemas/GasPriceFixed" + }, + { + "$ref": "#/components/schemas/GasPriceFixedEIP1559" + } + ] + } + }, + "publicRpcUri": { + "$ref": "#/components/schemas/RpcUri" + }, + "rpcUri": { + "$ref": "#/components/schemas/RpcUri" + }, + "safeAppsRpcUri": { + "$ref": "#/components/schemas/RpcUri" + }, + "shortName": { + "type": "string" + }, + "theme": { + "$ref": "#/components/schemas/Theme" + }, + "recommendedMasterCopyVersion": { "type": "string", - "enum": [ - "month", - "year" - ], "nullable": true }, - "type": { - "type": "string", - "enum": [ - "standard", - "premium", - "enterprise" + "relayer": { + "nullable": true, + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/Relayer" + } ] + } + }, + "required": [ + "chainId", + "chainName", + "description", + "l2", + "isTestnet", + "zk", + "nativeCurrency", + "transactionService", + "blockExplorerUriTemplate", + "beaconChainExplorerUriTemplate", + "disabledWallets", + "balancesProvider", + "features", + "gasPrice", + "publicRpcUri", + "rpcUri", + "safeAppsRpcUri", + "shortName", + "theme", + "relayer" + ] + }, + "ChainPage": { + "type": "object", + "properties": { + "count": { + "type": "number", + "nullable": true }, - "product": { + "next": { + "type": "string", + "nullable": true + }, + "previous": { "type": "string", "nullable": true + }, + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Chain" + } } }, "required": [ - "id", - "currentPrice", - "originalPrice", - "paymentMethod", - "currency", - "features", - "type", - "product" + "results" ] }, - "Subscription": { + "AboutChain": { "type": "object", "properties": { - "id": { + "transactionServiceBaseUri": { "type": "string" }, - "customerId": { + "name": { "type": "string" }, - "upstreamCustomerId": { + "version": { "type": "string" }, - "plan": { - "$ref": "#/components/schemas/SubscriptionPlan" - }, - "status": { - "type": "string", - "enum": [ - "active", - "canceled", - "incomplete", - "incomplete_expired", - "past_due", - "paused", - "trialing", - "unpaid" - ] - }, - "createdAt": { - "type": "number" - }, - "startAt": { - "type": "number" + "buildNumber": { + "type": "string" + } + }, + "required": [ + "transactionServiceBaseUri", + "name", + "version", + "buildNumber" + ] + }, + "Backbone": { + "type": "object", + "properties": { + "api_version": { + "type": "string" }, - "cancelledAt": { - "type": "number", + "headers": { + "type": "string", "nullable": true }, - "cancelAt": { - "type": "number", - "nullable": true + "host": { + "type": "string" }, - "currentPeriodStart": { - "type": "number", - "nullable": true + "name": { + "type": "string" }, - "currentPeriodEnd": { - "type": "number", - "nullable": true + "secure": { + "type": "boolean" }, - "metadata": { + "settings": { "type": "object", "nullable": true + }, + "version": { + "type": "string" } }, "required": [ - "id", - "customerId", - "upstreamCustomerId", - "plan", - "status", - "createdAt", - "startAt", - "cancelledAt", - "cancelAt" + "api_version", + "host", + "name", + "secure", + "settings", + "version" ] }, - "MarketingFeature": { + "MasterCopy": { "type": "object", "properties": { - "name": { + "address": { + "type": "string" + }, + "version": { "type": "string" } }, "required": [ - "name" + "address", + "version" ] }, - "Product": { + "IndexingStatus": { "type": "object", "properties": { - "id": { + "currentBlockNumber": { + "type": "number" + }, + "currentBlockTimestamp": { + "format": "date-time", "type": "string" }, - "active": { - "type": "boolean" + "erc20BlockNumber": { + "type": "number" }, - "description": { + "erc20BlockTimestamp": { + "format": "date-time", "type": "string" }, - "marketingFeatures": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MarketingFeature" - } + "erc20Synced": { + "type": "boolean" }, - "metadata": { - "type": "object" + "masterCopiesBlockNumber": { + "type": "number" }, - "name": { + "masterCopiesBlockTimestamp": { + "format": "date-time", "type": "string" + }, + "masterCopiesSynced": { + "type": "boolean" + }, + "synced": { + "type": "boolean" + }, + "lastSync": { + "type": "number" } }, "required": [ - "id", - "active", - "description", - "marketingFeatures", - "metadata", - "name" + "currentBlockNumber", + "currentBlockTimestamp", + "erc20BlockNumber", + "erc20BlockTimestamp", + "erc20Synced", + "masterCopiesBlockNumber", + "masterCopiesBlockTimestamp", + "masterCopiesSynced", + "synced", + "lastSync" ] }, - "Plan": { + "GasPriceResult": { "type": "object", "properties": { - "id": { - "type": "string" - }, - "name": { + "LastBlock": { "type": "string", - "nullable": true + "description": "Last block number", + "example": "23467872" }, - "description": { + "SafeGasPrice": { "type": "string", - "nullable": true - }, - "currentPrice": { - "type": "number" - }, - "originalPrice": { - "type": "number", - "nullable": true + "description": "Safe gas price recommendation (Gwei)", + "example": "0.496839934" }, - "paymentMethod": { + "ProposeGasPrice": { "type": "string", - "enum": [ - "fiat" - ] + "description": "Proposed gas price (Gwei)", + "example": "0.496840168" }, - "currency": { + "FastGasPrice": { "type": "string", - "enum": [ - "usd", - "eur" - ] - }, - "features": { - "type": "array", - "items": { - "type": "string" - } + "description": "Fast gas price recommendation (Gwei)", + "example": "0.55411917" }, - "billingCycle": { + "suggestBaseFee": { "type": "string", - "enum": [ - "month", - "year" - ], - "nullable": true + "description": "Base fee of the next pending block (Gwei)", + "example": "0.496839934" }, - "type": { + "gasUsedRatio": { "type": "string", - "enum": [ - "standard", - "premium", - "enterprise" - ] - }, - "product": { - "$ref": "#/components/schemas/Product" + "description": "Gas used ratio to estimate network congestion", + "example": "0.5,0.6,0.7" } }, "required": [ - "id", - "currentPrice", - "originalPrice", - "paymentMethod", - "currency", - "features", - "type", - "product" + "LastBlock", + "SafeGasPrice", + "ProposeGasPrice", + "FastGasPrice", + "suggestBaseFee", + "gasUsedRatio" ] }, - "UrlResponse": { + "GasPriceResponse": { "type": "object", "properties": { - "url": { - "type": "string" + "status": { + "type": "string", + "description": "Status code (\"1\" = success)", + "example": "1" + }, + "message": { + "type": "string", + "description": "Response message", + "example": "OK" + }, + "result": { + "description": "Gas price data", + "allOf": [ + { + "$ref": "#/components/schemas/GasPriceResult" + } + ] } }, "required": [ - "url" + "status", + "message", + "result" ] }, - "PaymentLink": { + "Collectible": { "type": "object", "properties": { - "id": { + "address": { "type": "string" }, - "url": { + "tokenName": { "type": "string" }, - "active": { - "type": "boolean" + "tokenSymbol": { + "type": "string" + }, + "logoUri": { + "type": "string" + }, + "id": { + "type": "string" + }, + "uri": { + "type": "string", + "nullable": true + }, + "name": { + "type": "string", + "nullable": true + }, + "description": { + "type": "string", + "nullable": true + }, + "imageUri": { + "type": "string", + "nullable": true }, "metadata": { - "type": "object" + "type": "object", + "nullable": true + } + }, + "required": [ + "address", + "tokenName", + "tokenSymbol", + "logoUri", + "id" + ] + }, + "CollectiblePage": { + "type": "object", + "properties": { + "count": { + "type": "number", + "nullable": true }, - "customText": { - "type": "object" + "next": { + "type": "string", + "nullable": true }, - "afterCompletion": { - "type": "object" + "previous": { + "type": "string", + "nullable": true }, - "lineItems": { + "results": { "type": "array", "items": { - "type": "object" + "$ref": "#/components/schemas/Collectible" } } }, "required": [ - "id", - "url", - "active", - "metadata" + "results" ] }, - "CheckoutSessionResult": { + "ActivityMetadata": { "type": "object", "properties": { - "sessionId": { + "name": { "type": "string" }, - "url": { + "description": { "type": "string" + }, + "maxPoints": { + "type": "number" } }, "required": [ - "sessionId", - "url" + "name", + "description", + "maxPoints" ] }, - "CheckoutSession": { + "Campaign": { "type": "object", "properties": { - "id": { + "resourceId": { "type": "string" }, - "object": { + "name": { "type": "string" }, - "amountSubtotal": { - "type": "number" - }, - "amountTotal": { - "type": "number" - }, - "cancelUrl": { + "description": { "type": "string" }, - "clientReferenceId": { - "type": "object", - "nullable": true - }, - "created": { - "type": "number" + "startDate": { + "type": "string" }, - "currency": { + "endDate": { "type": "string" }, - "customer": { - "type": "object", + "lastUpdated": { + "type": "string", "nullable": true }, - "expiresAt": { - "type": "number" + "activitiesMetadata": { + "nullable": true, + "type": "array", + "items": { + "$ref": "#/components/schemas/ActivityMetadata" + } }, - "metadata": { - "type": "object" + "rewardValue": { + "type": "string", + "nullable": true }, - "mode": { - "type": "string" + "rewardText": { + "type": "string", + "nullable": true }, - "paymentStatus": { - "type": "string" + "iconUrl": { + "type": "string", + "nullable": true }, - "status": { - "type": "string" + "safeAppUrl": { + "type": "string", + "nullable": true }, - "successUrl": { - "type": "string" + "partnerUrl": { + "type": "string", + "nullable": true }, - "url": { - "type": "object", + "isPromoted": { + "type": "boolean" + } + }, + "required": [ + "resourceId", + "name", + "description", + "startDate", + "endDate", + "isPromoted" + ] + }, + "CampaignPage": { + "type": "object", + "properties": { + "count": { + "type": "number", "nullable": true }, - "subscription": { - "type": "object", + "next": { + "type": "string", "nullable": true }, - "invoice": { - "type": "object", + "previous": { + "type": "string", "nullable": true + }, + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Campaign" + } } }, "required": [ - "id", - "object", - "amountSubtotal", - "amountTotal", - "cancelUrl", - "created", - "currency", - "expiresAt", - "metadata", - "mode", - "paymentStatus", - "status", - "successUrl" + "results" ] }, - "Position": { + "CampaignRank": { "type": "object", "properties": { - "balance": { + "holder": { "type": "string" }, - "fiatBalance": { - "type": "string" + "position": { + "type": "number" }, - "fiatConversion": { - "type": "string" + "boost": { + "type": "number" }, - "tokenInfo": { - "oneOf": [ - { - "$ref": "#/components/schemas/NativeToken" - }, - { - "$ref": "#/components/schemas/Erc20Token" - }, - { - "$ref": "#/components/schemas/Erc721Token" - } - ] + "totalPoints": { + "type": "number" }, - "fiatBalance24hChange": { + "totalBoostedPoints": { + "type": "number" + } + }, + "required": [ + "holder", + "position", + "boost", + "totalPoints", + "totalBoostedPoints" + ] + }, + "CampaignRankPage": { + "type": "object", + "properties": { + "count": { + "type": "number", + "nullable": true + }, + "next": { "type": "string", "nullable": true }, - "position_type": { + "previous": { "type": "string", - "enum": [ - "deposit", - "loan", - "locked", - "staked", - "reward", - "wallet", - "airdrop", - "margin", - "unknown" - ], "nullable": true + }, + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CampaignRank" + } } }, "required": [ - "balance", - "fiatBalance", - "fiatConversion", - "tokenInfo", - "fiatBalance24hChange", - "position_type" + "results" ] }, - "PositionGroup": { + "EligibilityRequest": { "type": "object", "properties": { - "name": { + "requestId": { "type": "string" }, - "items": { - "type": "array", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/Position" - } - ] - } + "sealedData": { + "type": "string" } }, "required": [ - "name", - "items" + "requestId", + "sealedData" ] }, - "ProtocolIcon": { + "Eligibility": { "type": "object", "properties": { - "url": { - "type": "string", - "nullable": true + "requestId": { + "type": "string" + }, + "isAllowed": { + "type": "boolean" + }, + "isVpn": { + "type": "boolean" } }, "required": [ - "url" + "requestId", + "isAllowed", + "isVpn" ] }, - "ProtocolMetadata": { + "LockingRank": { "type": "object", "properties": { - "name": { + "holder": { "type": "string" }, - "icon": { - "$ref": "#/components/schemas/ProtocolIcon" + "position": { + "type": "number" + }, + "lockedAmount": { + "type": "string" + }, + "unlockedAmount": { + "type": "string" + }, + "withdrawnAmount": { + "type": "string" } }, "required": [ - "name", - "icon" + "holder", + "position", + "lockedAmount", + "unlockedAmount", + "withdrawnAmount" ] }, - "Protocol": { + "LockingRankPage": { "type": "object", "properties": { - "protocol": { - "type": "string" + "count": { + "type": "number", + "nullable": true }, - "protocol_metadata": { - "$ref": "#/components/schemas/ProtocolMetadata" + "next": { + "type": "string", + "nullable": true }, - "fiatTotal": { - "type": "string" + "previous": { + "type": "string", + "nullable": true }, - "items": { + "results": { "type": "array", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/PositionGroup" - } - ] + "$ref": "#/components/schemas/LockingRank" } } }, "required": [ - "protocol", - "protocol_metadata", - "fiatTotal", - "items" + "results" ] }, - "PortfolioNativeToken": { + "LockEventItem": { "type": "object", "properties": { - "address": { - "type": "string" - }, - "decimals": { - "type": "number" + "eventType": { + "type": "string", + "enum": [ + "LOCKED" + ] }, - "logoUri": { + "executionDate": { "type": "string" }, - "name": { + "transactionHash": { "type": "string" }, - "symbol": { + "holder": { "type": "string" }, - "type": { - "type": "string", - "enum": [ - "NATIVE_TOKEN" - ] - }, - "chainId": { - "type": "string", - "description": "The chain ID" + "amount": { + "type": "string" }, - "trusted": { - "type": "boolean", - "description": "Whether the token is trusted (spam filter)" + "logIndex": { + "type": "string" } }, "required": [ - "address", - "decimals", - "logoUri", - "name", - "symbol", - "type", - "chainId", - "trusted" + "eventType", + "executionDate", + "transactionHash", + "holder", + "amount", + "logIndex" ] }, - "PortfolioErc20Token": { + "UnlockEventItem": { "type": "object", "properties": { - "address": { - "type": "string" - }, - "decimals": { - "type": "number" + "eventType": { + "type": "string", + "enum": [ + "UNLOCKED" + ] }, - "logoUri": { + "executionDate": { "type": "string" }, - "name": { + "transactionHash": { "type": "string" }, - "symbol": { + "holder": { "type": "string" }, - "type": { - "type": "string", - "enum": [ - "ERC20" - ] + "amount": { + "type": "string" }, - "chainId": { - "type": "string", - "description": "The chain ID" + "logIndex": { + "type": "string" }, - "trusted": { - "type": "boolean", - "description": "Whether the token is trusted (spam filter)" + "unlockIndex": { + "type": "string" } }, "required": [ - "address", - "decimals", - "logoUri", - "name", - "symbol", - "type", - "chainId", - "trusted" + "eventType", + "executionDate", + "transactionHash", + "holder", + "amount", + "logIndex", + "unlockIndex" ] }, - "PortfolioErc721Token": { + "WithdrawEventItem": { "type": "object", "properties": { - "address": { - "type": "string" - }, - "decimals": { - "type": "number" + "eventType": { + "type": "string", + "enum": [ + "WITHDRAWN" + ] }, - "logoUri": { + "executionDate": { "type": "string" }, - "name": { + "transactionHash": { "type": "string" }, - "symbol": { + "holder": { "type": "string" }, - "type": { - "type": "string", - "enum": [ - "ERC721" - ] + "amount": { + "type": "string" }, - "chainId": { - "type": "string", - "description": "The chain ID" + "logIndex": { + "type": "string" }, - "trusted": { - "type": "boolean", - "description": "Whether the token is trusted (spam filter)" + "unlockIndex": { + "type": "string" } }, "required": [ - "address", - "decimals", - "logoUri", - "name", - "symbol", - "type", - "chainId", - "trusted" + "eventType", + "executionDate", + "transactionHash", + "holder", + "amount", + "logIndex", + "unlockIndex" ] }, - "TokenBalance": { + "LockingEventPage": { "type": "object", "properties": { - "tokenInfo": { - "description": "Token information", - "oneOf": [ - { - "$ref": "#/components/schemas/PortfolioNativeToken" - }, - { - "$ref": "#/components/schemas/PortfolioErc20Token" - }, - { - "$ref": "#/components/schemas/PortfolioErc721Token" - } - ] - }, - "balance": { - "type": "string", - "description": "Balance in smallest unit as string integer. Use decimals to convert." + "count": { + "type": "number", + "nullable": true }, - "balanceFiat": { + "next": { "type": "string", - "description": "Balance in requested fiat currency. Decimal string without exponent notation or thousand separators.", - "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", - "example": "4801.653401839" + "nullable": true }, - "price": { + "previous": { "type": "string", - "description": "Token price in requested fiat currency. Decimal string without exponent notation or thousand separators.", - "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", - "example": "3890.12" + "nullable": true }, - "priceChangePercentage1d": { - "type": "string", - "description": "Price change as decimal (e.g., \"-0.0431\" for -4.31%). Decimal string without exponent notation.", - "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", - "example": "-0.0431" + "results": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/LockEventItem" + }, + { + "$ref": "#/components/schemas/UnlockEventItem" + }, + { + "$ref": "#/components/schemas/WithdrawEventItem" + } + ] + } } }, "required": [ - "tokenInfo", - "balance" + "results" ] }, - "AppPosition": { + "Contract": { "type": "object", "properties": { - "key": { - "type": "string", - "description": "Unique position key" - }, - "type": { - "type": "string", - "description": "Position type (e.g., staked, lending, liquidity)" + "address": { + "type": "string" }, "name": { - "type": "string", - "description": "Position name" - }, - "groupId": { - "type": "string", - "description": "Group ID for grouping related positions together" - }, - "tokenInfo": { - "description": "Token information", - "oneOf": [ - { - "$ref": "#/components/schemas/PortfolioNativeToken" - }, - { - "$ref": "#/components/schemas/PortfolioErc20Token" - }, - { - "$ref": "#/components/schemas/PortfolioErc721Token" - } - ] + "type": "string" }, - "receiptTokenAddress": { - "type": "string", - "description": "Receipt token address (pool address) representing this position. This is the contract address for the position token (LP token, staking receipt, etc.), not the underlying token." + "displayName": { + "type": "string" }, - "balance": { - "type": "string", - "description": "Balance in smallest unit as string integer. Use decimals to convert." + "logoUri": { + "type": "string" }, - "balanceFiat": { - "type": "string", - "description": "Balance in requested fiat currency. Decimal string without exponent notation or thousand separators.", - "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", - "example": "18638914.125656575" + "contractAbi": { + "type": "object", + "nullable": true }, - "priceChangePercentage1d": { - "type": "string", - "description": "Price change as decimal (e.g., \"-0.0431\" for -4.31%). Decimal string without exponent notation.", - "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", - "example": "-0.0431" + "trustedForDelegateCall": { + "type": "boolean" } }, "required": [ - "key", - "type", + "address", "name", - "tokenInfo", - "balance" + "displayName", + "logoUri", + "trustedForDelegateCall" ] }, - "AppPositionGroup": { + "TransactionDataDto": { "type": "object", "properties": { - "name": { + "data": { "type": "string", - "description": "Group name (e.g., \"Protocol A Vesting\")" + "description": "Hexadecimal value" }, - "items": { - "type": "array", - "description": "Positions in this group", - "items": { - "$ref": "#/components/schemas/AppPosition" - } + "to": { + "type": "string", + "description": "The target Ethereum address" } }, "required": [ - "name", - "items" + "data" ] }, - "AppBalanceAppInfo": { + "Operation": { + "type": "number", + "enum": [ + 0, + 1 + ], + "description": "Operation type: 0 for CALL, 1 for DELEGATE" + }, + "BaseDataDecoded": { "type": "object", "properties": { - "name": { - "type": "string", - "description": "Application name" - }, - "logoUrl": { - "type": "string", - "format": "uri", - "description": "Application logo URL (HTTPS)" + "method": { + "type": "string" }, - "url": { - "type": "string", - "format": "uri", - "description": "Application URL (HTTPS)" + "parameters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DataDecodedParameter" + } } }, "required": [ - "name" + "method" ] }, - "AppBalance": { + "MultiSend": { "type": "object", "properties": { - "appInfo": { - "description": "Application information", + "operation": { + "description": "Operation type: 0 for CALL, 1 for DELEGATE", "allOf": [ { - "$ref": "#/components/schemas/AppBalanceAppInfo" + "$ref": "#/components/schemas/Operation" } ] }, - "balanceFiat": { - "type": "string", - "description": "Total balance in fiat currency across all position groups. Decimal string without exponent notation or thousand separators.", - "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", - "example": "18638914.125656575" + "value": { + "type": "string" }, - "groups": { - "type": "array", - "description": "Position groups in this app, grouped by position name", - "items": { - "$ref": "#/components/schemas/AppPositionGroup" - } + "dataDecoded": { + "$ref": "#/components/schemas/BaseDataDecoded" + }, + "to": { + "type": "string" + }, + "data": { + "type": "string", + "nullable": true, + "description": "Hexadecimal encoded data", + "pattern": "^0x[0-9a-fA-F]*$" } }, "required": [ - "appInfo", - "balanceFiat", - "groups" + "operation", + "value", + "to", + "data" ] }, - "Portfolio": { + "DataDecodedParameter": { "type": "object", "properties": { - "totalBalanceFiat": { - "type": "string", - "description": "Total balance in fiat currency across all tokens and positions. Decimal string without exponent notation or thousand separators.", - "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", - "example": "954181237.094243" - }, - "totalTokenBalanceFiat": { - "type": "string", - "description": "Total balance in fiat currency for all token holdings. Decimal string without exponent notation or thousand separators.", - "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", - "example": "935542322.9685864" + "name": { + "type": "string" }, - "totalPositionsBalanceFiat": { - "type": "string", - "description": "Total balance in fiat currency for all app positions. Decimal string without exponent notation or thousand separators.", - "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", - "example": "18638914.125656575" + "type": { + "type": "string" }, - "tokenBalances": { - "description": "List of token balances", - "type": "array", - "items": { - "$ref": "#/components/schemas/TokenBalance" - } + "value": { + "description": "Parameter value - typically a string, but may be an array of strings for array types (e.g., address[], uint256[])", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] }, - "positionBalances": { - "description": "List of app balances", - "type": "array", - "items": { - "$ref": "#/components/schemas/AppBalance" - } + "valueDecoded": { + "oneOf": [ + { + "$ref": "#/components/schemas/BaseDataDecoded" + }, + { + "type": "array", + "items": { + "$ref": "#/components/schemas/MultiSend" + } + }, + { + "type": "null" + } + ] } }, "required": [ - "totalBalanceFiat", - "totalTokenBalanceFiat", - "totalPositionsBalanceFiat", - "tokenBalances", - "positionBalances" + "name", + "type", + "value" ] }, - "GasPriceOracle": { + "DataDecoded": { "type": "object", "properties": { - "type": { - "type": "string", - "enum": [ - "oracle" - ] - }, - "gasParameter": { + "method": { "type": "string" }, - "gweiFactor": { - "type": "string" + "parameters": { + "nullable": true, + "type": "array", + "items": { + "$ref": "#/components/schemas/DataDecodedParameter" + } }, - "uri": { - "type": "string" + "accuracy": { + "type": "string", + "enum": [ + "FULL_MATCH", + "PARTIAL_MATCH", + "ONLY_FUNCTION_MATCH", + "NO_MATCH", + "UNKNOWN" + ], + "default": "UNKNOWN" } }, "required": [ - "type", - "gasParameter", - "gweiFactor", - "uri" + "method" ] }, - "GasPriceFixed": { + "AddRecoveryModuleDto": { "type": "object", "properties": { - "type": { - "type": "string", - "enum": [ - "fixed" - ] - }, - "weiValue": { + "moduleAddress": { "type": "string" } }, "required": [ - "type", - "weiValue" + "moduleAddress" ] }, - "GasPriceFixedEIP1559": { + "GetEstimationDto": { "type": "object", "properties": { - "type": { - "type": "string", - "enum": [ - "fixed1559" - ] - }, - "maxFeePerGas": { + "to": { "type": "string" }, - "maxPriorityFeePerGas": { + "value": { "type": "string" + }, + "data": { + "type": "string", + "nullable": true + }, + "operation": { + "description": "Operation type: 0 for CALL, 1 for DELEGATE", + "allOf": [ + { + "$ref": "#/components/schemas/Operation" + } + ] } }, "required": [ - "type", - "maxFeePerGas", - "maxPriorityFeePerGas" + "to", + "value", + "operation" ] }, - "NativeCurrency": { + "EstimationResponse": { "type": "object", "properties": { - "decimals": { + "currentNonce": { "type": "number" }, - "logoUri": { - "type": "string" - }, - "name": { - "type": "string" + "recommendedNonce": { + "type": "number" }, - "symbol": { + "safeTxGas": { "type": "string" } }, "required": [ - "decimals", - "logoUri", - "name", - "symbol" + "currentNonce", + "recommendedNonce", + "safeTxGas" ] }, - "BlockExplorerUriTemplate": { + "GasToken": { "type": "object", "properties": { "address": { - "type": "string" - }, - "api": { - "type": "string" + "type": "string", + "description": "Gas token contract address", + "example": "0x0000000000000000000000000000000000000000" }, - "txHash": { - "type": "string" + "symbol": { + "type": "string", + "description": "The token's ticker symbol", + "example": "USDC" } }, "required": [ "address", - "api", - "txHash" + "symbol" ] }, - "BalancesProvider": { + "GasTokenPage": { "type": "object", "properties": { - "chainName": { + "count": { + "type": "number", + "nullable": true + }, + "next": { "type": "string", "nullable": true }, - "enabled": { - "type": "boolean" + "previous": { + "type": "string", + "nullable": true + }, + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GasToken" + } } }, "required": [ - "chainName", - "enabled" + "results" ] }, - "RpcUri": { + "Origin": { + "type": "string", + "enum": [ + "SAFE_APP", + "WALLET_CONNECT", + "TX_BUILDER", + "NATIVE" + ], + "description": "Transaction origin. Defaults to NATIVE when omitted." + }, + "FeePreviewTransactionDto": { "type": "object", "properties": { - "authentication": { - "type": "string", - "enum": [ - "API_KEY_PATH", - "NO_AUTHENTICATION", - "UNKNOWN" - ] + "to": { + "type": "string" }, "value": { "type": "string" + }, + "data": { + "type": "string" + }, + "operation": { + "description": "Operation type: 0 for CALL, 1 for DELEGATE", + "allOf": [ + { + "$ref": "#/components/schemas/Operation" + } + ] + }, + "gasToken": { + "type": "string", + "description": "Gas token address (0x0...0 for native token)", + "example": "0x0000000000000000000000000000000000000000" + }, + "numberSignatures": { + "type": "number", + "description": "Number of signatures required for execution", + "example": 2, + "minimum": 1 + }, + "nonce": { + "type": "string", + "description": "Safe nonce the transaction will use (uint256 string)", + "example": "42" + }, + "origin": { + "description": "Transaction origin. Defaults to NATIVE when omitted.", + "allOf": [ + { + "$ref": "#/components/schemas/Origin" + } + ] + }, + "fiatCode": { + "type": "string", + "description": "Fiat currency code for relay cost conversion (e.g. EUR, GBP). Defaults to USD.", + "example": "EUR" } }, "required": [ - "authentication", - "value" + "to", + "value", + "data", + "operation", + "gasToken", + "numberSignatures", + "nonce" ] }, - "Theme": { + "FeePreviewTxData": { "type": "object", "properties": { - "backgroundColor": { - "type": "string" + "chainId": { + "type": "string", + "description": "Chain ID", + "example": "1" }, - "textColor": { - "type": "string" + "safeAddress": { + "type": "string", + "description": "Safe address", + "example": "0x..." + }, + "safeTxGas": { + "type": "string", + "description": "Safe transaction gas", + "example": "150000" + }, + "baseGas": { + "type": "string", + "description": "Base gas for relay overhead", + "example": "48564" + }, + "gasPrice": { + "type": "string", + "description": "Gas price per gas unit. Denominated in wei when `gasToken` is the native token (zero address), or in the ERC20 gas token atomic units per gas otherwise", + "example": "195000000000000" + }, + "gasToken": { + "type": "string", + "description": "Gas token address", + "example": "0x0000000000000000000000000000000000000000" + }, + "refundReceiver": { + "type": "string", + "description": "Refund receiver address", + "example": "0x0000000000000000000000000000000000000000" + }, + "numberSignatures": { + "type": "number", + "description": "Number of signatures", + "example": 2 } }, "required": [ - "backgroundColor", - "textColor" + "chainId", + "safeAddress", + "safeTxGas", + "baseGas", + "gasPrice", + "gasToken", + "refundReceiver", + "numberSignatures" ] }, - "Relayer": { + "FeePreviewRelayCost": { "type": "object", "properties": { - "type": { + "fiatCode": { "type": "string", - "enum": [ - "GTF", - "RELAY_FEE", - "DAILY_LIMIT", - "NO_FEE_CAMPAIGN" - ], - "nullable": true - }, - "safeCreationSponsored": { - "type": "boolean" - }, - "safeTransactionSponsored": { - "type": "boolean" - }, - "enableTenderlySimulationBeforeRelay": { - "type": "boolean" + "description": "Fiat currency code", + "example": "USD" + }, + "fiatValue": { + "type": "string", + "description": "Relay cost as a string", + "example": "0.0025" } }, "required": [ - "type", - "safeCreationSponsored", - "safeTransactionSponsored", - "enableTenderlySimulationBeforeRelay" + "fiatCode", + "fiatValue" ] }, - "Chain": { + "FeePreviewValuationDetail": { "type": "object", "properties": { - "chainId": { - "type": "string" - }, - "chainName": { - "type": "string" - }, - "description": { - "type": "string" - }, - "chainLogoUri": { + "tokenAddress": { "type": "string", - "nullable": true - }, - "l2": { - "type": "boolean" + "description": "Token contract address (absent for native transfers)" }, - "isTestnet": { - "type": "boolean" + "symbol": { + "type": "string", + "description": "Token symbol", + "example": "USDC" }, - "zk": { - "type": "boolean" + "amount": { + "type": "string", + "description": "Token amount", + "example": "1000" }, - "nativeCurrency": { - "$ref": "#/components/schemas/NativeCurrency" + "priceUsd": { + "type": "number", + "description": "Token price in USD" }, - "transactionService": { - "type": "string" + "valueUsd": { + "type": "number", + "description": "Token value in USD" + } + }, + "required": [ + "symbol", + "amount" + ] + }, + "FeePreviewFeeBreakdown": { + "type": "object", + "properties": { + "txValueUsd": { + "type": "number", + "description": "Transaction value in USD", + "example": 1000 }, - "blockExplorerUriTemplate": { - "$ref": "#/components/schemas/BlockExplorerUriTemplate" + "trailingVolumeUsd": { + "type": "number", + "description": "Trailing volume in USD that fed tier selection", + "example": 0 }, - "beaconChainExplorerUriTemplate": { - "type": "object" + "tierBps": { + "type": "number", + "description": "Tier fee in basis points", + "example": 5 }, - "disabledWallets": { - "type": "array", - "items": { - "type": "string" - } + "gtfFeeUsd": { + "type": "number", + "description": "GTF fee in USD", + "example": 0.5 }, - "ensRegistryAddress": { - "type": "string", - "nullable": true + "relayCostUsd": { + "type": "number", + "description": "Relay cost in USD", + "example": 38.22 }, - "balancesProvider": { - "$ref": "#/components/schemas/BalancesProvider" + "totalUsd": { + "type": "number", + "description": "Total fee in USD", + "example": 38.72 }, - "features": { - "type": "array", - "items": { - "type": "string" - } + "numberSignatures": { + "type": "number", + "description": "Number of signatures", + "example": 2 }, - "gasPrice": { + "valuationDetails": { "type": "array", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/GasPriceOracle" - }, - { - "$ref": "#/components/schemas/GasPriceFixed" - }, - { - "$ref": "#/components/schemas/GasPriceFixedEIP1559" - } - ] + "$ref": "#/components/schemas/FeePreviewValuationDetail" } + } + }, + "required": [ + "txValueUsd", + "trailingVolumeUsd", + "tierBps", + "gtfFeeUsd", + "relayCostUsd", + "totalUsd", + "numberSignatures", + "valuationDetails" + ] + }, + "FeePreviewResponse": { + "type": "object", + "properties": { + "txData": { + "$ref": "#/components/schemas/FeePreviewTxData" }, - "publicRpcUri": { - "$ref": "#/components/schemas/RpcUri" - }, - "rpcUri": { - "$ref": "#/components/schemas/RpcUri" - }, - "safeAppsRpcUri": { - "$ref": "#/components/schemas/RpcUri" - }, - "shortName": { - "type": "string" - }, - "theme": { - "$ref": "#/components/schemas/Theme" - }, - "recommendedMasterCopyVersion": { - "type": "string", - "nullable": true + "relayCost": { + "description": "Relay cost. Present when the relay fee flow applies.", + "allOf": [ + { + "$ref": "#/components/schemas/FeePreviewRelayCost" + } + ] }, - "relayer": { - "nullable": true, - "type": "object", + "feeBreakdown": { + "description": "GTF fee breakdown, as returned by the fee-engine service. Present when the GTF fee flow applies.", "allOf": [ { - "$ref": "#/components/schemas/Relayer" + "$ref": "#/components/schemas/FeePreviewFeeBreakdown" } ] + }, + "maxFeeCapUsd": { + "type": "number", + "description": "Maximum fee cap in USD (buffered max fee). Present when the GTF fee flow applies." } }, "required": [ - "chainId", - "chainName", - "description", - "l2", - "isTestnet", - "zk", - "nativeCurrency", - "transactionService", - "blockExplorerUriTemplate", - "beaconChainExplorerUriTemplate", - "disabledWallets", - "balancesProvider", - "features", - "gasPrice", - "publicRpcUri", - "rpcUri", - "safeAppsRpcUri", - "shortName", - "theme", - "relayer" + "txData" ] }, - "ChainPage": { + "TypedDataParameter": { "type": "object", "properties": { - "count": { - "type": "number", - "nullable": true - }, - "next": { - "type": "string", - "nullable": true - }, - "previous": { - "type": "string", - "nullable": true + "name": { + "type": "string" }, - "results": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Chain" - } + "type": { + "type": "string" } }, "required": [ - "results" + "name", + "type" ] }, - "AboutChain": { + "TypedDataDomain": { "type": "object", "properties": { - "transactionServiceBaseUri": { - "type": "string" + "chainId": { + "type": "number" }, "name": { "type": "string" }, + "salt": { + "type": "string" + }, + "verifyingContract": { + "type": "string" + }, "version": { "type": "string" }, - "buildNumber": { - "type": "string" + "safe": { + "type": "string" + } + } + }, + "TypedData": { + "type": "object", + "properties": { + "domain": { + "$ref": "#/components/schemas/TypedDataDomain" + }, + "primaryType": { + "type": "string" + }, + "types": { + "type": "object", + "additionalProperties": { + "items": { + "$ref": "#/components/schemas/TypedDataParameter" + }, + "type": "array" + } + }, + "message": { + "type": "object", + "additionalProperties": true } }, "required": [ - "transactionServiceBaseUri", - "name", - "version", - "buildNumber" + "domain", + "primaryType", + "types", + "message" ] }, - "Backbone": { + "AddressInfo": { "type": "object", "properties": { - "api_version": { + "value": { "type": "string" }, - "headers": { + "name": { "type": "string", "nullable": true }, - "host": { - "type": "string" - }, - "name": { - "type": "string" - }, - "secure": { - "type": "boolean" - }, - "settings": { - "type": "object", + "logoUri": { + "type": "string", "nullable": true - }, - "version": { - "type": "string" } }, "required": [ - "api_version", - "host", - "name", - "secure", - "settings", - "version" + "value" ] }, - "MasterCopy": { + "MessageConfirmation": { "type": "object", "properties": { - "address": { - "type": "string" + "owner": { + "$ref": "#/components/schemas/AddressInfo" }, - "version": { + "signature": { "type": "string" } }, "required": [ - "address", - "version" + "owner", + "signature" ] }, - "IndexingStatus": { + "SafeAppInfo": { "type": "object", "properties": { - "currentBlockNumber": { - "type": "number" - }, - "currentBlockTimestamp": { - "format": "date-time", - "type": "string" - }, - "erc20BlockNumber": { + "id": { "type": "number" }, - "erc20BlockTimestamp": { - "format": "date-time", + "name": { "type": "string" }, - "erc20Synced": { - "type": "boolean" - }, - "masterCopiesBlockNumber": { - "type": "number" - }, - "masterCopiesBlockTimestamp": { - "format": "date-time", + "url": { "type": "string" }, - "masterCopiesSynced": { - "type": "boolean" - }, - "synced": { - "type": "boolean" - }, - "lastSync": { - "type": "number" + "logoUri": { + "type": "string", + "nullable": true } }, "required": [ - "currentBlockNumber", - "currentBlockTimestamp", - "erc20BlockNumber", - "erc20BlockTimestamp", - "erc20Synced", - "masterCopiesBlockNumber", - "masterCopiesBlockTimestamp", - "masterCopiesSynced", - "synced", - "lastSync" + "id", + "name", + "url" ] }, - "GasPriceResult": { + "Message": { "type": "object", "properties": { - "LastBlock": { - "type": "string", - "description": "Last block number", - "example": "23467872" + "messageHash": { + "type": "string" }, - "SafeGasPrice": { + "status": { "type": "string", - "description": "Safe gas price recommendation (Gwei)", - "example": "0.496839934" + "enum": [ + "NEEDS_CONFIRMATION", + "CONFIRMED" + ] }, - "ProposeGasPrice": { + "logoUri": { "type": "string", - "description": "Proposed gas price (Gwei)", - "example": "0.496840168" + "nullable": true, + "deprecated": true }, - "FastGasPrice": { + "name": { "type": "string", - "description": "Fast gas price recommendation (Gwei)", - "example": "0.55411917" + "nullable": true, + "deprecated": true }, - "suggestBaseFee": { + "message": { + "oneOf": [ + { + "type": "string" + }, + { + "$ref": "#/components/schemas/TypedData" + } + ] + }, + "creationTimestamp": { + "type": "number" + }, + "modifiedTimestamp": { + "type": "number" + }, + "confirmationsSubmitted": { + "type": "number" + }, + "confirmationsRequired": { + "type": "number" + }, + "proposedBy": { + "nullable": true, + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/AddressInfo" + } + ] + }, + "confirmations": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MessageConfirmation" + } + }, + "preparedSignature": { "type": "string", - "description": "Base fee of the next pending block (Gwei)", - "example": "0.496839934" + "nullable": true }, - "gasUsedRatio": { + "origin": { "type": "string", - "description": "Gas used ratio to estimate network congestion", - "example": "0.5,0.6,0.7" + "nullable": true + }, + "safeAppInfo": { + "nullable": true, + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/SafeAppInfo" + } + ] + }, + "safeAppId": { + "type": "number", + "nullable": true, + "deprecated": true } }, "required": [ - "LastBlock", - "SafeGasPrice", - "ProposeGasPrice", - "FastGasPrice", - "suggestBaseFee", - "gasUsedRatio" + "messageHash", + "status", + "logoUri", + "name", + "message", + "creationTimestamp", + "modifiedTimestamp", + "confirmationsSubmitted", + "confirmationsRequired", + "proposedBy", + "confirmations", + "preparedSignature", + "origin", + "safeAppInfo", + "safeAppId" ] }, - "GasPriceResponse": { + "MessageItem": { "type": "object", "properties": { + "messageHash": { + "type": "string" + }, "status": { "type": "string", - "description": "Status code (\"1\" = success)", - "example": "1" + "enum": [ + "NEEDS_CONFIRMATION", + "CONFIRMED" + ] + }, + "logoUri": { + "type": "string", + "nullable": true, + "deprecated": true + }, + "name": { + "type": "string", + "nullable": true, + "deprecated": true + }, + "message": { + "oneOf": [ + { + "type": "string" + }, + { + "$ref": "#/components/schemas/TypedData" + } + ] + }, + "creationTimestamp": { + "type": "number" + }, + "modifiedTimestamp": { + "type": "number" + }, + "confirmationsSubmitted": { + "type": "number" + }, + "confirmationsRequired": { + "type": "number" + }, + "proposedBy": { + "nullable": true, + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/AddressInfo" + } + ] + }, + "confirmations": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MessageConfirmation" + } + }, + "preparedSignature": { + "type": "string", + "nullable": true }, - "message": { + "origin": { "type": "string", - "description": "Response message", - "example": "OK" + "nullable": true }, - "result": { - "description": "Gas price data", + "safeAppInfo": { + "nullable": true, + "type": "object", "allOf": [ { - "$ref": "#/components/schemas/GasPriceResult" + "$ref": "#/components/schemas/SafeAppInfo" } ] + }, + "safeAppId": { + "type": "number", + "nullable": true, + "deprecated": true + }, + "type": { + "type": "string", + "enum": [ + "MESSAGE" + ] } }, "required": [ + "messageHash", "status", + "logoUri", + "name", "message", - "result" + "creationTimestamp", + "modifiedTimestamp", + "confirmationsSubmitted", + "confirmationsRequired", + "proposedBy", + "confirmations", + "preparedSignature", + "origin", + "safeAppInfo", + "safeAppId", + "type" ] }, - "Collectible": { + "DateLabel": { "type": "object", "properties": { - "address": { - "type": "string" - }, - "tokenName": { - "type": "string" - }, - "tokenSymbol": { - "type": "string" - }, - "logoUri": { - "type": "string" - }, - "id": { - "type": "string" - }, - "uri": { - "type": "string", - "nullable": true - }, - "name": { - "type": "string", - "nullable": true - }, - "description": { - "type": "string", - "nullable": true - }, - "imageUri": { + "type": { "type": "string", - "nullable": true + "enum": [ + "DATE_LABEL" + ] }, - "metadata": { - "type": "object", - "nullable": true + "timestamp": { + "type": "number" } }, "required": [ - "address", - "tokenName", - "tokenSymbol", - "logoUri", - "id" + "type", + "timestamp" ] }, - "CollectiblePage": { + "MessagePage": { "type": "object", "properties": { "count": { @@ -8136,7 +10922,14 @@ "results": { "type": "array", "items": { - "$ref": "#/components/schemas/Collectible" + "oneOf": [ + { + "$ref": "#/components/schemas/MessageItem" + }, + { + "$ref": "#/components/schemas/DateLabel" + } + ] } } }, @@ -8144,658 +10937,682 @@ "results" ] }, - "ActivityMetadata": { + "CreateMessageDto": { "type": "object", "properties": { - "name": { - "type": "string" + "message": { + "oneOf": [ + { + "type": "string" + }, + { + "$ref": "#/components/schemas/TypedData" + } + ] }, - "description": { + "safeAppId": { + "type": "number", + "nullable": true, + "deprecated": true + }, + "signature": { "type": "string" }, - "maxPoints": { - "type": "number" + "origin": { + "type": "string", + "nullable": true } }, "required": [ - "name", - "description", - "maxPoints" + "message", + "signature" ] }, - "Campaign": { + "UpdateMessageSignatureDto": { "type": "object", "properties": { - "resourceId": { + "signature": { "type": "string" + } + }, + "required": [ + "signature" + ] + }, + "UserWallet": { + "type": "object", + "properties": { + "id": { + "type": "number" }, - "name": { + "address": { "type": "string" + } + }, + "required": [ + "id", + "address" + ] + }, + "UserWithWallets": { + "type": "object", + "properties": { + "id": { + "type": "number" }, - "description": { - "type": "string" + "status": { + "type": "number", + "enum": [ + 0, + 1 + ] }, - "startDate": { + "wallets": { + "type": "array", + "items": { + "$ref": "#/components/schemas/UserWallet" + } + } + }, + "required": [ + "id", + "status", + "wallets" + ] + }, + "CreatedUserWithWallet": { + "type": "object", + "properties": { + "id": { + "type": "number" + } + }, + "required": [ + "id" + ] + }, + "WalletAddedToUser": { + "type": "object", + "properties": { + "id": { + "type": "number" + } + }, + "required": [ + "id" + ] + }, + "SpaceAddressBookItemDto": { + "type": "object", + "properties": { + "name": { "type": "string" }, - "endDate": { + "address": { "type": "string" }, - "lastUpdated": { - "type": "string", - "nullable": true + "chainIds": { + "type": "array", + "items": { + "type": "string" + } }, - "activitiesMetadata": { - "nullable": true, + "tagIds": { + "description": "IDs of the workspace tags assigned to the contact", "type": "array", "items": { - "$ref": "#/components/schemas/ActivityMetadata" + "type": "number" } }, - "rewardValue": { + "createdBy": { "type": "string", - "nullable": true + "description": "Email or wallet address of the creator, \"Unknown user\" if the user has no display identity, or \"Deleted user\"" }, - "rewardText": { - "type": "string", - "nullable": true + "createdByUserId": { + "type": "number", + "description": "User ID of the creator" }, - "iconUrl": { + "lastUpdatedBy": { "type": "string", - "nullable": true + "description": "Email or wallet address of the last editor, \"Unknown user\" if the user has no display identity, or \"Deleted user\"" + }, + "lastUpdatedByUserId": { + "type": "number", + "description": "User ID of the last editor" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "name", + "address", + "chainIds", + "tagIds", + "createdBy", + "createdByUserId", + "lastUpdatedBy", + "lastUpdatedByUserId", + "createdAt", + "updatedAt" + ] + }, + "SpaceAddressBookTagDto": { + "type": "object", + "properties": { + "id": { + "type": "number" }, - "safeAppUrl": { - "type": "string", - "nullable": true + "name": { + "type": "string" }, - "partnerUrl": { + "color": { "type": "string", - "nullable": true + "enum": [ + "slate", + "clay", + "rose", + "lilac", + "iris", + "cobalt", + "sky", + "lagoon" + ] }, - "isPromoted": { - "type": "boolean" + "contactCount": { + "type": "number", + "description": "Number of contacts that have this tag" } }, "required": [ - "resourceId", + "id", "name", - "description", - "startDate", - "endDate", - "isPromoted" + "color", + "contactCount" ] }, - "CampaignPage": { + "SpaceAddressBookDto": { "type": "object", "properties": { - "count": { - "type": "number", - "nullable": true - }, - "next": { + "spaceUuid": { "type": "string", - "nullable": true + "description": "Space UUID" }, - "previous": { - "type": "string", - "nullable": true + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SpaceAddressBookItemDto" + } }, - "results": { + "tags": { + "description": "All tags defined in the workspace address book", "type": "array", "items": { - "$ref": "#/components/schemas/Campaign" + "$ref": "#/components/schemas/SpaceAddressBookTagDto" } } }, "required": [ - "results" + "spaceUuid", + "data", + "tags" ] }, - "CampaignRank": { + "UpsertAddressBookItem": { "type": "object", "properties": { - "holder": { + "name": { "type": "string" }, - "position": { - "type": "number" - }, - "boost": { - "type": "number" + "address": { + "type": "string" }, - "totalPoints": { - "type": "number" + "chainIds": { + "type": "array", + "items": { + "type": "string" + } }, - "totalBoostedPoints": { - "type": "number" + "tags": { + "maxItems": 3, + "description": "Tag names of the contact (replaces the current tags when provided; omit to leave them unchanged)", + "type": "array", + "items": { + "type": "string" + } } }, "required": [ - "holder", - "position", - "boost", - "totalPoints", - "totalBoostedPoints" + "name", + "address", + "chainIds" ] }, - "CampaignRankPage": { + "UpsertAddressBookItemsDto": { "type": "object", "properties": { - "count": { - "type": "number", - "nullable": true - }, - "next": { - "type": "string", - "nullable": true - }, - "previous": { - "type": "string", - "nullable": true - }, - "results": { + "items": { "type": "array", "items": { - "$ref": "#/components/schemas/CampaignRank" + "$ref": "#/components/schemas/UpsertAddressBookItem" } } }, "required": [ - "results" + "items" ] }, - "EligibilityRequest": { + "SetContactTagsItem": { "type": "object", "properties": { - "requestId": { + "address": { "type": "string" }, - "sealedData": { - "type": "string" + "tags": { + "maxItems": 3, + "description": "The full set of tag names for the contact. 'Workspace Safe' and 'Signer' aren't allowed, in any case", + "type": "array", + "items": { + "type": "string" + } } }, "required": [ - "requestId", - "sealedData" + "address", + "tags" ] }, - "Eligibility": { + "SetContactTagsDto": { "type": "object", "properties": { - "requestId": { - "type": "string" - }, - "isAllowed": { - "type": "boolean" - }, - "isVpn": { - "type": "boolean" + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SetContactTagsItem" + }, + "minItems": 1, + "description": "At most as many entries as the address book can hold, each address at most once" } }, "required": [ - "requestId", - "isAllowed", - "isVpn" + "items" ] }, - "LockingRank": { + "CreateTagDto": { "type": "object", "properties": { - "holder": { - "type": "string" - }, - "position": { - "type": "number" - }, - "lockedAmount": { - "type": "string" - }, - "unlockedAmount": { - "type": "string" - }, - "withdrawnAmount": { - "type": "string" + "name": { + "type": "string", + "maxLength": 32, + "description": "'Workspace Safe' and 'Signer' aren't allowed, in any case" } }, "required": [ - "holder", - "position", - "lockedAmount", - "unlockedAmount", - "withdrawnAmount" + "name" ] }, - "LockingRankPage": { + "RenameTagDto": { "type": "object", "properties": { - "count": { - "type": "number", - "nullable": true - }, - "next": { - "type": "string", - "nullable": true - }, - "previous": { + "name": { "type": "string", - "nullable": true - }, - "results": { - "type": "array", - "items": { - "$ref": "#/components/schemas/LockingRank" - } + "maxLength": 32, + "description": "'Workspace Safe' and 'Signer' aren't allowed, in any case" } }, "required": [ - "results" + "name" ] }, - "LockEventItem": { + "AddressBookRequestItemDto": { "type": "object", "properties": { - "eventType": { - "type": "string", - "enum": [ - "LOCKED" - ] - }, - "executionDate": { - "type": "string" + "id": { + "type": "number" }, - "transactionHash": { + "name": { "type": "string" }, - "holder": { + "address": { "type": "string" }, - "amount": { - "type": "string" + "chainIds": { + "type": "array", + "items": { + "type": "string" + } }, - "logIndex": { - "type": "string" - } - }, - "required": [ - "eventType", - "executionDate", - "transactionHash", - "holder", - "amount", - "logIndex" - ] - }, - "UnlockEventItem": { - "type": "object", - "properties": { - "eventType": { + "requestedBy": { "type": "string", - "enum": [ - "UNLOCKED" - ] + "description": "Email or wallet address of the requester, \"Unknown user\" if the user has no display identity, or \"Deleted user\"" }, - "executionDate": { - "type": "string" + "requestedByUserId": { + "type": "number", + "description": "User ID of the requester" }, - "transactionHash": { - "type": "string" + "reviewedBy": { + "type": "string", + "nullable": true, + "description": "Email or wallet address of the reviewing admin, \"Unknown user\", \"Deleted user\", or null when still PENDING" }, - "holder": { - "type": "string" + "reviewedByUserId": { + "type": "number", + "nullable": true, + "description": "User ID of the reviewing admin, null when still PENDING" }, - "amount": { - "type": "string" + "status": { + "type": "string", + "enum": [ + "PENDING", + "APPROVED", + "REJECTED" + ] }, - "logIndex": { + "createdAt": { + "format": "date-time", "type": "string" }, - "unlockIndex": { + "updatedAt": { + "format": "date-time", "type": "string" } }, "required": [ - "eventType", - "executionDate", - "transactionHash", - "holder", - "amount", - "logIndex", - "unlockIndex" + "id", + "name", + "address", + "chainIds", + "requestedBy", + "requestedByUserId", + "reviewedBy", + "reviewedByUserId", + "status", + "createdAt", + "updatedAt" ] }, - "WithdrawEventItem": { + "AddressBookRequestsDto": { "type": "object", "properties": { - "eventType": { + "spaceUuid": { "type": "string", - "enum": [ - "WITHDRAWN" - ] - }, - "executionDate": { - "type": "string" - }, - "transactionHash": { - "type": "string" - }, - "holder": { - "type": "string" - }, - "amount": { - "type": "string" - }, - "logIndex": { - "type": "string" + "description": "Space UUID" }, - "unlockIndex": { - "type": "string" + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AddressBookRequestItemDto" + } } }, "required": [ - "eventType", - "executionDate", - "transactionHash", - "holder", - "amount", - "logIndex", - "unlockIndex" + "spaceUuid", + "data" ] }, - "LockingEventPage": { + "CreateAddressBookRequestDto": { "type": "object", "properties": { - "count": { - "type": "number", - "nullable": true - }, - "next": { + "name": { "type": "string", - "nullable": true + "maxLength": 50, + "description": "Name of the proposed contact" }, - "previous": { + "address": { "type": "string", - "nullable": true + "description": "Address of the contact to propose for the space address book" }, - "results": { + "chainIds": { + "description": "Chain ids the contact applies to (at least one, duplicates are removed)", "type": "array", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/LockEventItem" - }, - { - "$ref": "#/components/schemas/UnlockEventItem" - }, - { - "$ref": "#/components/schemas/WithdrawEventItem" - } - ] + "type": "string" } } }, "required": [ - "results" + "name", + "address", + "chainIds" ] }, - "Contract": { + "CreateSpaceDto": { "type": "object", "properties": { - "address": { - "type": "string" - }, "name": { "type": "string" - }, - "displayName": { - "type": "string" - }, - "logoUri": { - "type": "string" - }, - "contractAbi": { - "type": "object", - "nullable": true - }, - "trustedForDelegateCall": { - "type": "boolean" } }, "required": [ - "address", - "name", - "displayName", - "logoUri", - "trustedForDelegateCall" + "name" ] }, - "TransactionDataDto": { + "CreateSpaceResponse": { "type": "object", "properties": { - "data": { - "type": "string", - "description": "Hexadecimal value" + "name": { + "type": "string" }, - "to": { + "uuid": { "type": "string", - "description": "The target Ethereum address" + "description": "Space UUID" } }, "required": [ - "data" + "name", + "uuid" ] }, - "Operation": { - "type": "number", - "enum": [ - 0, - 1 - ], - "description": "Operation type: 0 for CALL, 1 for DELEGATE" - }, - "BaseDataDecoded": { + "UserDto": { "type": "object", "properties": { - "method": { - "type": "string" - }, - "parameters": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DataDecodedParameter" - } + "id": { + "type": "number" } }, "required": [ - "method" + "id" ] }, - "MultiSend": { + "SpaceMemberDto": { "type": "object", "properties": { - "operation": { - "description": "Operation type: 0 for CALL, 1 for DELEGATE", - "allOf": [ - { - "$ref": "#/components/schemas/Operation" - } + "role": { + "type": "string", + "enum": [ + "ADMIN", + "MEMBER" ] }, - "value": { + "name": { "type": "string" }, - "dataDecoded": { - "$ref": "#/components/schemas/BaseDataDecoded" + "invitedBy": { + "type": "number", + "nullable": true }, - "to": { + "inviteExpiresAt": { + "format": "date-time", + "type": "string", + "nullable": true + }, + "invitedByName": { "type": "string" }, - "data": { + "status": { "type": "string", - "nullable": true, - "description": "Hexadecimal encoded data", - "pattern": "^0x[0-9a-fA-F]*$" + "enum": [ + "INVITED", + "ACTIVE", + "DECLINED" + ] + }, + "user": { + "$ref": "#/components/schemas/UserDto" } }, "required": [ - "operation", - "value", - "to", - "data" + "role", + "name", + "invitedBy", + "inviteExpiresAt", + "status", + "user" ] }, - "DataDecodedParameter": { + "GetSpaceResponse": { "type": "object", "properties": { + "uuid": { + "type": "string", + "description": "Space UUID" + }, "name": { "type": "string" }, - "type": { - "type": "string" + "members": { + "description": "Members of the space. A pending (INVITED) member only sees their own membership row here, not the other members.", + "type": "array", + "items": { + "$ref": "#/components/schemas/SpaceMemberDto" + } }, - "value": { - "description": "Parameter value - typically a string, but may be an array of strings for array types (e.g., address[], uint256[])", - "oneOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] + "memberCount": { + "type": "number", + "description": "Total count of ACTIVE members in the space", + "example": 5 }, - "valueDecoded": { - "oneOf": [ - { - "$ref": "#/components/schemas/BaseDataDecoded" - }, - { - "type": "array", - "items": { - "$ref": "#/components/schemas/MultiSend" - } - }, - { - "type": "null" - } - ] + "safeCount": { + "type": "number", + "description": "Total count of Safes in the space", + "example": 5 + }, + "experimentalFeatures": { + "type": "array", + "description": "Experimental features this Workspace has opted into.", + "items": { + "type": "string", + "enum": [ + "POLICY_RECIPIENT_ALLOWLIST" + ] + } } }, "required": [ + "uuid", "name", - "type", - "value" + "members", + "memberCount", + "safeCount", + "experimentalFeatures" ] }, - "DataDecoded": { + "UpdateSpaceDto": { "type": "object", "properties": { - "method": { + "name": { "type": "string" }, - "parameters": { - "nullable": true, + "status": { + "type": "string", + "enum": [ + "ACTIVE" + ] + }, + "experimentalFeatures": { "type": "array", + "description": "Replaces the stored set; [] opts out of all. Omit to leave it unchanged.", "items": { - "$ref": "#/components/schemas/DataDecodedParameter" + "type": "string", + "enum": [ + "POLICY_RECIPIENT_ALLOWLIST" + ] } - }, - "accuracy": { - "type": "string", - "enum": [ - "FULL_MATCH", - "PARTIAL_MATCH", - "ONLY_FUNCTION_MATCH", - "NO_MATCH", - "UNKNOWN" - ], - "default": "UNKNOWN" } - }, - "required": [ - "method" - ] + } }, - "AddRecoveryModuleDto": { + "UpdateSpaceResponse": { "type": "object", "properties": { - "moduleAddress": { - "type": "string" + "uuid": { + "type": "string", + "description": "Space UUID" } }, "required": [ - "moduleAddress" + "uuid" ] }, - "GetEstimationDto": { + "SpaceAuditLogEntryDto": { "type": "object", "properties": { - "to": { - "type": "string" - }, - "value": { - "type": "string" - }, - "data": { + "id": { "type": "string", - "nullable": true + "description": "Monotonic entry id (bigint serialized as string)" }, - "operation": { - "description": "Operation type: 0 for CALL, 1 for DELEGATE", - "allOf": [ - { - "$ref": "#/components/schemas/Operation" - } + "eventType": { + "type": "string", + "enum": [ + "SPACE_CREATED", + "SPACE_UPDATED", + "SPACE_DELETED", + "MEMBER_INVITED", + "MEMBER_INVITE_ACCEPTED", + "MEMBER_INVITE_DECLINED", + "MEMBER_INVITE_RENEWED", + "MEMBER_ROLE_UPDATED", + "MEMBER_ALIAS_UPDATED", + "MEMBER_REMOVED", + "MEMBER_LEFT", + "SAFE_ADDED", + "SAFE_REMOVED", + "ADDRESS_BOOK_UPSERTED", + "ADDRESS_BOOK_DELETED", + "ADDRESS_BOOK_REQUEST_CREATED", + "ADDRESS_BOOK_REQUEST_REJECTED", + "ADDRESS_BOOK_TAGS_UPDATED", + "ADDRESS_BOOK_TAG_CREATED", + "ADDRESS_BOOK_TAG_RENAMED", + "ADDRESS_BOOK_TAG_DELETED" ] - } - }, - "required": [ - "to", - "value", - "operation" - ] - }, - "EstimationResponse": { - "type": "object", - "properties": { - "currentNonce": { - "type": "number" }, - "recommendedNonce": { + "actorUserId": { "type": "number" }, - "safeTxGas": { - "type": "string" - } - }, - "required": [ - "currentNonce", - "recommendedNonce", - "safeTxGas" - ] - }, - "GasToken": { - "type": "object", - "properties": { - "address": { + "actor": { "type": "string", - "description": "Gas token contract address", - "example": "0x0000000000000000000000000000000000000000" + "description": "Resolved (and masked) display string of the acting user." }, - "symbol": { + "targetUser": { "type": "string", - "description": "The token's ticker symbol", - "example": "USDC" + "nullable": true, + "description": "Resolved (and masked) display string of the affected user, when the event has one." + }, + "payload": { + "type": "object", + "description": "Event-specific payload, allowlisted per event type. Clients must treat every field as optional." + }, + "createdAt": { + "format": "date-time", + "type": "string" } }, "required": [ - "address", - "symbol" + "id", + "eventType", + "actorUserId", + "actor", + "targetUser", + "payload", + "createdAt" ] }, - "GasTokenPage": { + "SpaceAuditLogPage": { "type": "object", "properties": { "count": { @@ -8813,7 +11630,7 @@ "results": { "type": "array", "items": { - "$ref": "#/components/schemas/GasToken" + "$ref": "#/components/schemas/SpaceAuditLogEntryDto" } } }, @@ -8821,1656 +11638,1699 @@ "results" ] }, - "Origin": { - "type": "string", - "enum": [ - "SAFE_APP", - "WALLET_CONNECT", - "TX_BUILDER", - "NATIVE" - ], - "description": "Transaction origin. Defaults to NATIVE when omitted." - }, - "FeePreviewTransactionDto": { - "type": "object", - "properties": { - "to": { - "type": "string" - }, - "value": { - "type": "string" - }, - "data": { - "type": "string" - }, - "operation": { - "description": "Operation type: 0 for CALL, 1 for DELEGATE", - "allOf": [ - { - "$ref": "#/components/schemas/Operation" - } - ] - }, - "gasToken": { - "type": "string", - "description": "Gas token address (0x0...0 for native token)", - "example": "0x0000000000000000000000000000000000000000" - }, - "numberSignatures": { - "type": "number", - "description": "Number of signatures required for execution", - "example": 2, - "minimum": 1 - }, - "nonce": { - "type": "string", - "description": "Safe nonce the transaction will use (uint256 string)", - "example": "42" - }, - "origin": { - "description": "Transaction origin. Defaults to NATIVE when omitted.", - "allOf": [ - { - "$ref": "#/components/schemas/Origin" - } - ] - }, - "fiatCode": { - "type": "string", - "description": "Fiat currency code for relay cost conversion (e.g. EUR, GBP). Defaults to USD.", - "example": "EUR" - } - }, - "required": [ - "to", - "value", - "data", - "operation", - "gasToken", - "numberSignatures", - "nonce" - ] - }, - "FeePreviewTxData": { + "SpaceAuditLogActorDto": { "type": "object", "properties": { - "chainId": { - "type": "string", - "description": "Chain ID", - "example": "1" - }, - "safeAddress": { - "type": "string", - "description": "Safe address", - "example": "0x..." - }, - "safeTxGas": { - "type": "string", - "description": "Safe transaction gas", - "example": "150000" - }, - "baseGas": { - "type": "string", - "description": "Base gas for relay overhead", - "example": "48564" - }, - "gasPrice": { - "type": "string", - "description": "Gas price per gas unit. Denominated in wei when `gasToken` is the native token (zero address), or in the ERC20 gas token atomic units per gas otherwise", - "example": "195000000000000" - }, - "gasToken": { - "type": "string", - "description": "Gas token address", - "example": "0x0000000000000000000000000000000000000000" - }, - "refundReceiver": { - "type": "string", - "description": "Refund receiver address", - "example": "0x0000000000000000000000000000000000000000" - }, - "numberSignatures": { - "type": "number", - "description": "Number of signatures", - "example": 2 + "actorUserId": { + "type": "number" + }, + "actor": { + "type": "string", + "description": "Resolved (and masked) display string of the actor." } }, "required": [ - "chainId", - "safeAddress", - "safeTxGas", - "baseGas", - "gasPrice", - "gasToken", - "refundReceiver", - "numberSignatures" + "actorUserId", + "actor" ] }, - "FeePreviewRelayCost": { + "SpaceSafeDto": { "type": "object", "properties": { - "fiatCode": { - "type": "string", - "description": "Fiat currency code", - "example": "USD" + "chainId": { + "type": "string" }, - "fiatValue": { - "type": "string", - "description": "Relay cost as a string", - "example": "0.0025" + "address": { + "type": "string" } }, "required": [ - "fiatCode", - "fiatValue" + "chainId", + "address" ] }, - "FeePreviewValuationDetail": { + "AddressBookItem": { "type": "object", "properties": { - "tokenAddress": { - "type": "string", - "description": "Token contract address (absent for native transfers)" - }, - "symbol": { - "type": "string", - "description": "Token symbol", - "example": "USDC" - }, - "amount": { - "type": "string", - "description": "Token amount", - "example": "1000" + "name": { + "type": "string" }, - "priceUsd": { - "type": "number", - "description": "Token price in USD" + "address": { + "type": "string" }, - "valueUsd": { - "type": "number", - "description": "Token value in USD" + "chainIds": { + "type": "array", + "items": { + "type": "string" + } } }, "required": [ - "symbol", - "amount" + "name", + "address", + "chainIds" ] }, - "FeePreviewFeeBreakdown": { + "CreateSpaceSafesDto": { "type": "object", "properties": { - "txValueUsd": { - "type": "number", - "description": "Transaction value in USD", - "example": 1000 - }, - "trailingVolumeUsd": { - "type": "number", - "description": "Trailing volume in USD that fed tier selection", - "example": 0 - }, - "tierBps": { - "type": "number", - "description": "Tier fee in basis points", - "example": 5 - }, - "gtfFeeUsd": { - "type": "number", - "description": "GTF fee in USD", - "example": 0.5 - }, - "relayCostUsd": { - "type": "number", - "description": "Relay cost in USD", - "example": 38.22 - }, - "totalUsd": { - "type": "number", - "description": "Total fee in USD", - "example": 38.72 - }, - "numberSignatures": { - "type": "number", - "description": "Number of signatures", - "example": 2 + "safes": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SpaceSafeDto" + } }, - "valuationDetails": { + "addressBookItems": { + "description": "Address book entries to upsert for the added Safes, in the same transaction: if either write fails, neither is kept.", "type": "array", "items": { - "$ref": "#/components/schemas/FeePreviewValuationDetail" + "$ref": "#/components/schemas/AddressBookItem" } } }, "required": [ - "txValueUsd", - "trailingVolumeUsd", - "tierBps", - "gtfFeeUsd", - "relayCostUsd", - "totalUsd", - "numberSignatures", - "valuationDetails" + "safes" ] }, - "FeePreviewResponse": { + "GetSpacesSafesResponse": { "type": "object", "properties": { - "txData": { - "$ref": "#/components/schemas/FeePreviewTxData" - }, - "relayCost": { - "description": "Relay cost. Present when the relay fee flow applies.", - "allOf": [ - { - "$ref": "#/components/schemas/FeePreviewRelayCost" + "safes": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" } - ] + }, + "example": { + "{chainId}": [ + "0x..." + ] + } }, - "feeBreakdown": { - "description": "GTF fee breakdown, as returned by the fee-engine service. Present when the GTF fee flow applies.", - "allOf": [ - { - "$ref": "#/components/schemas/FeePreviewFeeBreakdown" + "spaceUuid": { + "type": "string", + "description": "Space UUID" + } + }, + "required": [ + "safes", + "spaceUuid" + ] + }, + "GetSpaceSafeResponse": { + "type": "object", + "properties": { + "safes": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" } - ] - }, - "maxFeeCapUsd": { - "type": "number", - "description": "Maximum fee cap in USD (buffered max fee). Present when the GTF fee flow applies." + }, + "example": { + "{chainId}": [ + "0x..." + ] + } } }, "required": [ - "txData" + "safes" ] }, - "TypedDataParameter": { + "DeleteSpaceSafesDto": { "type": "object", "properties": { - "name": { - "type": "string" - }, - "type": { - "type": "string" + "safes": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SpaceSafeDto" + } } }, "required": [ - "name", - "type" + "safes" ] }, - "TypedDataDomain": { + "WalletInviteUserDto": { "type": "object", "properties": { - "chainId": { - "type": "number" + "type": { + "type": "string", + "enum": [ + "wallet" + ] }, - "name": { + "address": { "type": "string" }, - "salt": { - "type": "string" + "role": { + "type": "string", + "enum": [ + "ADMIN", + "MEMBER" + ] }, - "verifyingContract": { - "type": "string" + "name": { + "type": "string", + "maxLength": 255 + } + }, + "required": [ + "type", + "address", + "role", + "name" + ] + }, + "EmailInviteUserDto": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "email" + ] }, - "version": { - "type": "string" + "email": { + "type": "string", + "format": "email", + "maxLength": 255 + }, + "role": { + "type": "string", + "enum": [ + "ADMIN", + "MEMBER" + ] + }, + "name": { + "type": "string", + "maxLength": 255 } - } + }, + "required": [ + "type", + "email", + "role", + "name" + ] }, - "TypedData": { + "InviteUsersDto": { "type": "object", "properties": { - "domain": { - "$ref": "#/components/schemas/TypedDataDomain" - }, - "primaryType": { - "type": "string" - }, - "types": { - "type": "object", - "additionalProperties": { - "items": { - "$ref": "#/components/schemas/TypedDataParameter" - }, - "type": "array" + "users": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/WalletInviteUserDto" + }, + { + "$ref": "#/components/schemas/EmailInviteUserDto" + } + ] } - }, - "message": { - "type": "object", - "additionalProperties": true } }, "required": [ - "domain", - "primaryType", - "types", - "message" + "users" ] }, - "AddressInfo": { + "Invitation": { "type": "object", "properties": { - "value": { - "type": "string" + "userId": { + "type": "number" }, "name": { + "type": "string" + }, + "spaceUuid": { "type": "string", - "nullable": true + "description": "Space UUID" }, - "logoUri": { + "role": { + "type": "string", + "enum": [ + "ADMIN", + "MEMBER" + ] + }, + "status": { "type": "string", + "enum": [ + "INVITED", + "ACTIVE", + "DECLINED" + ] + }, + "invitedBy": { + "type": "number", "nullable": true } }, "required": [ - "value" + "userId", + "name", + "spaceUuid", + "role", + "status", + "invitedBy" ] }, - "MessageConfirmation": { + "AcceptInviteDto": { "type": "object", "properties": { - "owner": { - "$ref": "#/components/schemas/AddressInfo" - }, - "signature": { - "type": "string" + "name": { + "type": "string", + "maxLength": 255 } }, "required": [ - "owner", - "signature" + "name" ] }, - "Message": { + "MemberUser": { "type": "object", "properties": { - "messageHash": { - "type": "string" + "id": { + "type": "number" }, "status": { "type": "string", "enum": [ - "NEEDS_CONFIRMATION", - "CONFIRMED" - ] - }, - "logoUri": { - "type": "string", - "nullable": true - }, - "name": { - "type": "string", - "nullable": true - }, - "message": { - "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/components/schemas/TypedData" - } + "PENDING", + "ACTIVE" ] }, - "creationTimestamp": { - "type": "number" - }, - "modifiedTimestamp": { - "type": "number" - }, - "confirmationsSubmitted": { - "type": "number" - }, - "confirmationsRequired": { - "type": "number" - }, - "proposedBy": { - "$ref": "#/components/schemas/AddressInfo" - }, - "confirmations": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MessageConfirmation" - } - }, - "preparedSignature": { + "email": { "type": "string", "nullable": true }, - "origin": { + "address": { "type": "string", "nullable": true } }, "required": [ - "messageHash", + "id", "status", - "message", - "creationTimestamp", - "modifiedTimestamp", - "confirmationsSubmitted", - "confirmationsRequired", - "proposedBy", - "confirmations" + "email", + "address" ] }, - "MessageItem": { + "MemberDto": { "type": "object", "properties": { - "messageHash": { - "type": "string" + "id": { + "type": "number" }, - "status": { + "role": { "type": "string", "enum": [ - "NEEDS_CONFIRMATION", - "CONFIRMED" + "ADMIN", + "MEMBER" ] }, - "logoUri": { + "status": { "type": "string", - "nullable": true + "enum": [ + "INVITED", + "ACTIVE", + "DECLINED" + ] }, "name": { + "type": "string" + }, + "alias": { "type": "string", "nullable": true }, - "message": { - "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/components/schemas/TypedData" - } - ] - }, - "creationTimestamp": { - "type": "number" - }, - "modifiedTimestamp": { - "type": "number" - }, - "confirmationsSubmitted": { - "type": "number" - }, - "confirmationsRequired": { - "type": "number" - }, - "proposedBy": { - "$ref": "#/components/schemas/AddressInfo" - }, - "confirmations": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MessageConfirmation" - } - }, - "preparedSignature": { - "type": "string", + "invitedBy": { + "type": "number", "nullable": true }, - "origin": { + "inviteExpiresAt": { + "format": "date-time", "type": "string", "nullable": true }, - "type": { - "type": "string", - "enum": [ - "MESSAGE" - ] - } - }, - "required": [ - "messageHash", - "status", - "message", - "creationTimestamp", - "modifiedTimestamp", - "confirmationsSubmitted", - "confirmationsRequired", - "proposedBy", - "confirmations", - "type" - ] - }, - "DateLabel": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "DATE_LABEL" - ] + "createdAt": { + "format": "date-time", + "type": "string" }, - "timestamp": { - "type": "number" + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/MemberUser" } }, "required": [ - "type", - "timestamp" + "id", + "role", + "status", + "name", + "invitedBy", + "createdAt", + "updatedAt", + "user" ] }, - "MessagePage": { + "MembersDto": { "type": "object", "properties": { - "count": { - "type": "number", - "nullable": true - }, - "next": { - "type": "string", - "nullable": true - }, - "previous": { - "type": "string", - "nullable": true - }, - "results": { + "members": { "type": "array", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/MessageItem" - }, - { - "$ref": "#/components/schemas/DateLabel" - } - ] + "$ref": "#/components/schemas/MemberDto" } } }, "required": [ - "results" + "members" ] }, - "CreateMessageDto": { + "UpdateRoleDto": { "type": "object", "properties": { - "message": { - "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/components/schemas/TypedData" - } - ] - }, - "safeAppId": { - "type": "number", - "nullable": true, - "deprecated": true - }, - "signature": { - "type": "string" - }, - "origin": { + "role": { "type": "string", - "nullable": true + "enum": [ + "ADMIN", + "MEMBER" + ] } }, "required": [ - "message", - "signature" + "role" ] }, - "UpdateMessageSignatureDto": { + "UpdateMemberAliasDto": { "type": "object", "properties": { - "signature": { - "type": "string" + "alias": { + "type": "string", + "description": "The new alias for the member" } }, "required": [ - "signature" + "alias" ] }, - "UserWallet": { + "CounterfactualSafeDto": { "type": "object", "properties": { - "id": { - "type": "number" + "chainId": { + "type": "string" }, "address": { "type": "string" - } - }, - "required": [ - "id", - "address" - ] - }, - "UserWithWallets": { - "type": "object", - "properties": { - "id": { - "type": "number" }, - "status": { - "type": "number", - "enum": [ - 0, - 1 - ] + "factoryAddress": { + "type": "string" }, - "wallets": { + "masterCopy": { + "type": "string" + }, + "saltNonce": { + "type": "string" + }, + "safeVersion": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "owners": { "type": "array", "items": { - "$ref": "#/components/schemas/UserWallet" + "type": "string" } + }, + "fallbackHandler": { + "type": "string", + "nullable": true + }, + "to": { + "type": "string", + "nullable": true + }, + "data": { + "type": "string" + }, + "paymentToken": { + "type": "string", + "nullable": true + }, + "payment": { + "type": "string", + "nullable": true + }, + "paymentReceiver": { + "type": "string", + "nullable": true } }, "required": [ - "id", - "status", - "wallets" - ] - }, - "CreatedUserWithWallet": { - "type": "object", - "properties": { - "id": { - "type": "number" - } - }, - "required": [ - "id" + "chainId", + "address", + "factoryAddress", + "masterCopy", + "saltNonce", + "safeVersion", + "threshold", + "owners", + "data" ] }, - "WalletAddedToUser": { + "CreateCounterfactualSafesDto": { "type": "object", "properties": { - "id": { - "type": "number" + "safes": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CounterfactualSafeDto" + } } }, "required": [ - "id" + "safes" ] }, - "SpaceAddressBookItemDto": { + "GetCounterfactualSafeItem": { "type": "object", "properties": { - "name": { + "address": { "type": "string" }, - "address": { + "factoryAddress": { "type": "string" }, - "chainIds": { + "masterCopy": { + "type": "string" + }, + "saltNonce": { + "type": "string" + }, + "safeVersion": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "owners": { "type": "array", "items": { "type": "string" } }, - "createdBy": { + "fallbackHandler": { "type": "string", - "description": "Email or wallet address of the creator, \"Unknown user\" if the user has no display identity, or \"Deleted user\"" + "nullable": true }, - "createdByUserId": { - "type": "number", - "description": "User ID of the creator" + "to": { + "type": "string", + "nullable": true }, - "lastUpdatedBy": { + "data": { + "type": "string" + }, + "paymentToken": { "type": "string", - "description": "Email or wallet address of the last editor, \"Unknown user\" if the user has no display identity, or \"Deleted user\"" + "nullable": true }, - "lastUpdatedByUserId": { - "type": "number", - "description": "User ID of the last editor" + "payment": { + "type": "string", + "nullable": true }, - "createdAt": { - "format": "date-time", + "paymentReceiver": { + "type": "string", + "nullable": true + } + }, + "required": [ + "address", + "factoryAddress", + "masterCopy", + "saltNonce", + "safeVersion", + "threshold", + "owners", + "fallbackHandler", + "to", + "data", + "paymentToken", + "payment", + "paymentReceiver" + ] + }, + "GetCounterfactualSafesResponse": { + "type": "object", + "properties": { + "safes": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GetCounterfactualSafeItem" + } + }, + "example": { + "{chainId}": [ + { + "address": "0x...", + "factoryAddress": "0x...", + "masterCopy": "0x...", + "saltNonce": "1712000000000", + "safeVersion": "1.4.1", + "threshold": 1, + "owners": [ + "0x..." + ], + "fallbackHandler": "0x...", + "to": null, + "data": "0x...", + "paymentToken": null, + "payment": null, + "paymentReceiver": null + } + ] + } + } + }, + "required": [ + "safes" + ] + }, + "DeleteCounterfactualSafeDto": { + "type": "object", + "properties": { + "chainId": { "type": "string" }, - "updatedAt": { - "format": "date-time", + "address": { "type": "string" } }, "required": [ - "name", - "address", - "chainIds", - "createdBy", - "createdByUserId", - "lastUpdatedBy", - "lastUpdatedByUserId", - "createdAt", - "updatedAt" + "chainId", + "address" ] }, - "SpaceAddressBookDto": { + "DeleteCounterfactualSafesDto": { "type": "object", "properties": { - "spaceUuid": { - "type": "string", - "description": "Space UUID" - }, - "data": { + "safes": { "type": "array", "items": { - "$ref": "#/components/schemas/SpaceAddressBookItemDto" + "$ref": "#/components/schemas/DeleteCounterfactualSafeDto" } } }, "required": [ - "spaceUuid", - "data" + "safes" ] }, - "AddressBookItem": { + "SingleRecipientAnalysisResultDto": { "type": "object", "properties": { - "name": { - "type": "string" + "severity": { + "type": "string", + "description": "Severity level indicating the importance and risk", + "enum": [ + "OK", + "INFO", + "WARN", + "CRITICAL" + ] }, - "address": { - "type": "string" + "type": { + "type": "string", + "description": "Recipient interaction status code", + "enum": [ + "NEW_RECIPIENT", + "RECURRING_RECIPIENT", + "LOW_ACTIVITY", + "FAILED" + ], + "example": "NEW_RECIPIENT" }, - "chainIds": { - "type": "array", - "items": { - "type": "string" - } + "title": { + "type": "string", + "description": "User-facing title of the finding" + }, + "description": { + "type": "string", + "description": "Detailed description explaining the finding and its implications" + }, + "error": { + "type": "string", + "description": "Error message for failed analysis" } }, "required": [ - "name", - "address", - "chainIds" + "severity", + "type", + "title", + "description" ] }, - "UpsertAddressBookItemsDto": { + "SingleRecipientAnalysisDto": { "type": "object", "properties": { - "items": { + "RECIPIENT_INTERACTION": { + "description": "Analysis results related to recipient interaction history. Shows whether this is a new or recurring recipient.", + "example": [ + { + "severity": "INFO", + "type": "NEW_RECIPIENT", + "title": "New recipient", + "description": "This is the first time you are interacting with this recipient." + } + ], "type": "array", "items": { - "$ref": "#/components/schemas/AddressBookItem" + "$ref": "#/components/schemas/SingleRecipientAnalysisResultDto" + } + }, + "RECIPIENT_ACTIVITY": { + "description": "Analysis results related to recipient activity. Shows whether this is a low activity recipient. (Available only for Safes)", + "example": [ + { + "severity": "WARN", + "type": "LOW_ACTIVITY", + "title": "Low activity recipient", + "description": "This address has few transactions." + } + ], + "type": "array", + "items": { + "$ref": "#/components/schemas/SingleRecipientAnalysisResultDto" } + }, + "isSafe": { + "type": "boolean", + "description": "Indicates whether the analyzed recipient address is a Safe.", + "example": false } }, "required": [ - "items" + "RECIPIENT_INTERACTION", + "isSafe" ] }, - "AddressBookRequestItemDto": { + "CounterpartyAnalysisRequestDto": { "type": "object", "properties": { - "id": { - "type": "number" - }, - "name": { - "type": "string" - }, - "address": { - "type": "string" - }, - "chainIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "requestedBy": { + "to": { "type": "string", - "description": "Email or wallet address of the requester, \"Unknown user\" if the user has no display identity, or \"Deleted user\"" + "description": "Recipient address of the transaction." }, - "requestedByUserId": { - "type": "number", - "description": "User ID of the requester" + "value": { + "type": "string", + "description": "Amount to send with the transaction." }, - "reviewedBy": { + "data": { "type": "string", - "nullable": true, - "description": "Email or wallet address of the reviewing admin, \"Unknown user\", \"Deleted user\", or null when still PENDING" + "description": "Hex-encoded data payload for the transaction." }, - "reviewedByUserId": { + "operation": { "type": "number", - "nullable": true, - "description": "User ID of the reviewing admin, null when still PENDING" - }, - "status": { - "type": "string", "enum": [ - "PENDING", - "APPROVED", - "REJECTED" - ] - }, - "createdAt": { - "format": "date-time", - "type": "string" - }, - "updatedAt": { - "format": "date-time", - "type": "string" + 0, + 1 + ], + "description": "Operation type: 0 for CALL, 1 for DELEGATECALL." } }, "required": [ - "id", - "name", - "address", - "chainIds", - "requestedBy", - "requestedByUserId", - "reviewedBy", - "reviewedByUserId", - "status", - "createdAt", - "updatedAt" + "to", + "value", + "data", + "operation" ] }, - "AddressBookRequestsDto": { + "RecipientResultDto": { "type": "object", "properties": { - "spaceUuid": { + "severity": { "type": "string", - "description": "Space UUID" + "description": "Severity level indicating the importance and risk", + "enum": [ + "OK", + "INFO", + "WARN", + "CRITICAL" + ] }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AddressBookRequestItemDto" - } + "type": { + "type": "string", + "description": "Bridge compatibility status code", + "enum": [ + "NEW_RECIPIENT", + "RECURRING_RECIPIENT", + "LOW_ACTIVITY", + "INCOMPATIBLE_SAFE", + "MISSING_OWNERSHIP", + "UNSUPPORTED_NETWORK", + "DIFFERENT_SAFE_SETUP", + "FAILED" + ], + "example": "MISSING_OWNERSHIP" + }, + "title": { + "type": "string", + "description": "User-facing title of the finding" + }, + "description": { + "type": "string", + "description": "Detailed description explaining the finding and its implications" + }, + "error": { + "type": "string", + "description": "Error message for failed analysis" + }, + "targetChainId": { + "type": "string", + "description": "Target chain ID for bridge operations. Only present for BridgeStatus." } }, "required": [ - "spaceUuid", - "data" + "severity", + "type", + "title", + "description" ] }, - "CreateAddressBookRequestDto": { + "RecipientAnalysisDto": { "type": "object", "properties": { - "name": { - "type": "string", - "maxLength": 50, - "description": "Name of the proposed contact" + "isSafe": { + "type": "boolean", + "description": "Indicates whether the analyzed recipient address is a Safe.", + "example": true }, - "address": { - "type": "string", - "description": "Address of the contact to propose for the space address book" + "RECIPIENT_INTERACTION": { + "description": "Analysis results related to recipient interaction history. Shows whether this is a new or recurring recipient.", + "example": [ + { + "severity": "INFO", + "type": "NEW_RECIPIENT", + "title": "New recipient", + "description": "This is the first time you are interacting with this recipient." + } + ], + "type": "array", + "items": { + "$ref": "#/components/schemas/RecipientResultDto" + } }, - "chainIds": { - "description": "Chain ids the contact applies to (at least one, duplicates are removed)", + "RECIPIENT_ACTIVITY": { + "description": "Analysis results related to recipient activity frequency. Shows whether this is a low activity recipient.", + "example": [ + { + "severity": "WARN", + "type": "LOW_ACTIVITY", + "title": "Low activity recipient", + "description": "This address has few transactions." + } + ], "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/RecipientResultDto" + } + }, + "BRIDGE": { + "description": "Analysis results for cross-chain bridge operations. Identifies compatibility issues, ownership problems, or unsupported networks.", + "example": [ + { + "severity": "WARN", + "type": "MISSING_OWNERSHIP", + "title": "No ownership on target chain", + "description": "You do not have ownership of a Safe on the target chain.", + "targetChainId": "137" + } + ], + "type": "array", + "items": { + "$ref": "#/components/schemas/RecipientResultDto" } } }, "required": [ - "name", - "address", - "chainIds" + "isSafe" ] }, - "CreateSpaceDto": { + "ContractAnalysisResultDto": { "type": "object", "properties": { - "name": { - "type": "string" + "severity": { + "type": "string", + "description": "Severity level indicating the importance and risk", + "enum": [ + "OK", + "INFO", + "WARN", + "CRITICAL" + ] + }, + "type": { + "type": "string", + "description": "Contract verification status code", + "enum": [ + "VERIFIED", + "NOT_VERIFIED", + "NOT_VERIFIED_BY_SAFE", + "VERIFICATION_UNAVAILABLE", + "NEW_CONTRACT", + "KNOWN_CONTRACT", + "UNEXPECTED_DELEGATECALL", + "UNOFFICIAL_FALLBACK_HANDLER", + "FAILED" + ], + "example": "VERIFIED" + }, + "title": { + "type": "string", + "description": "User-facing title of the finding" + }, + "description": { + "type": "string", + "description": "Detailed description explaining the finding and its implications" + }, + "error": { + "type": "string", + "description": "Error message for failed analysis" } }, "required": [ - "name" + "severity", + "type", + "title", + "description" ] }, - "CreateSpaceResponse": { + "FallbackHandlerInfoDto": { "type": "object", "properties": { + "address": { + "type": "string", + "description": "Address of the fallback handler contract" + }, "name": { - "type": "string" + "type": "string", + "description": "Name of the fallback handler contract" }, - "uuid": { + "logoUrl": { "type": "string", - "description": "Space UUID" + "description": "Logo URL for the fallback handler contract" } }, "required": [ - "name", - "uuid" + "address" ] }, - "UserDto": { + "FallbackHandlerAnalysisResultDto": { "type": "object", "properties": { - "id": { - "type": "number" + "severity": { + "type": "string", + "description": "Severity level indicating the importance and risk", + "enum": [ + "OK", + "INFO", + "WARN", + "CRITICAL" + ] + }, + "type": { + "type": "string", + "description": "Status code for unofficial fallback handler", + "enum": [ + "UNOFFICIAL_FALLBACK_HANDLER" + ], + "example": "VERIFIED" + }, + "title": { + "type": "string", + "description": "User-facing title of the finding" + }, + "description": { + "type": "string", + "description": "Detailed description explaining the finding and its implications" + }, + "error": { + "type": "string", + "description": "Error message for failed analysis" + }, + "fallbackHandler": { + "description": "Information about the fallback handler", + "allOf": [ + { + "$ref": "#/components/schemas/FallbackHandlerInfoDto" + } + ] } }, "required": [ - "id" + "severity", + "type", + "title", + "description" ] }, - "SpaceMemberDto": { + "ContractAnalysisDto": { "type": "object", "properties": { - "role": { + "logoUrl": { "type": "string", - "enum": [ - "ADMIN", - "MEMBER" - ] + "description": "Logo URL for the contract", + "example": "https://example.com/logo.png" }, "name": { - "type": "string" - }, - "invitedBy": { - "type": "number", - "nullable": true - }, - "inviteExpiresAt": { - "format": "date-time", "type": "string", - "nullable": true + "description": "Name of the contract", + "example": "Uniswap V3 Router" }, - "invitedByName": { - "type": "string" + "CONTRACT_VERIFICATION": { + "description": "Analysis results for contract verification status. Shows whether contracts are verified and source code is available.", + "example": [ + { + "severity": "INFO", + "type": "VERIFIED", + "title": "Verified contract", + "description": "This contract has been verified and its source code is available" + } + ], + "type": "array", + "items": { + "$ref": "#/components/schemas/ContractAnalysisResultDto" + } }, - "status": { - "type": "string", - "enum": [ - "INVITED", - "ACTIVE", - "DECLINED" - ] + "CONTRACT_INTERACTION": { + "description": "Analysis results related to contract interaction history. Shows whether this is a new or previously interacted contract.", + "example": [ + { + "severity": "INFO", + "type": "NEW_CONTRACT", + "title": "New contract", + "description": "This is the first time you are interacting with this contract" + } + ], + "type": "array", + "items": { + "$ref": "#/components/schemas/ContractAnalysisResultDto" + } }, - "user": { - "$ref": "#/components/schemas/UserDto" + "DELEGATECALL": { + "description": "Analysis results for delegatecall operations. Identifies unexpected or potentially dangerous delegate calls.", + "example": [ + { + "severity": "CRITICAL", + "type": "UNEXPECTED_DELEGATECALL", + "title": "Unexpected delegatecall", + "description": "An unexpected delegatecall operation was detected that could be dangerous" + } + ], + "type": "array", + "items": { + "$ref": "#/components/schemas/ContractAnalysisResultDto" + } + }, + "FALLBACK_HANDLER": { + "description": "Analysis results for setFallbackHandler operations. Identifies untrusted or unofficial fallback handlers in the transactions.", + "example": [ + { + "severity": "WARN", + "type": "UNOFFICIAL_FALLBACK_HANDLER", + "title": "Unofficial fallback handler", + "description": "Verify the fallback handler is trusted and secure before proceeding.", + "fallbackHandler": { + "address": "0x123", + "name": "CompatibilityFallbackHandler", + "logoUrl": "https://example.com/logo.png" + } + } + ], + "type": "array", + "items": { + "$ref": "#/components/schemas/FallbackHandlerAnalysisResultDto" + } } - }, - "required": [ - "role", - "name", - "invitedBy", - "inviteExpiresAt", - "status", - "user" - ] + } }, - "GetSpaceResponse": { + "DeadlockAnalysisResultDto": { "type": "object", "properties": { - "uuid": { + "severity": { "type": "string", - "description": "Space UUID" + "description": "Severity level indicating the importance and risk", + "enum": [ + "OK", + "INFO", + "WARN", + "CRITICAL" + ] }, - "name": { - "type": "string" + "type": { + "type": "string", + "description": "Deadlock analysis status code", + "enum": [ + "DEADLOCK_DETECTED", + "NESTED_SAFE_WARNING", + "FAILED" + ], + "example": "DEADLOCK_DETECTED" }, - "members": { - "description": "Members of the space. A pending (INVITED) member only sees their own membership row here, not the other members.", - "type": "array", - "items": { - "$ref": "#/components/schemas/SpaceMemberDto" - } + "title": { + "type": "string", + "description": "User-facing title of the finding" }, - "memberCount": { - "type": "number", - "description": "Total count of ACTIVE members in the space", - "example": 5 + "description": { + "type": "string", + "description": "Detailed description explaining the finding and its implications" }, - "safeCount": { - "type": "number", - "description": "Total count of Safes in the space", - "example": 5 + "error": { + "type": "string", + "description": "Error message for failed analysis" } }, "required": [ - "uuid", - "name", - "members", - "memberCount", - "safeCount" + "severity", + "type", + "title", + "description" ] }, - "UpdateSpaceDto": { + "DeadlockAnalysisDto": { "type": "object", "properties": { - "name": { - "type": "string" - }, - "status": { - "type": "string", - "enum": [ - "ACTIVE" - ] + "DEADLOCK": { + "description": "Deadlock analysis findings. Identifies signing deadlock risks in nested Safe configurations.", + "example": [ + { + "severity": "CRITICAL", + "type": "DEADLOCK_DETECTED", + "title": "Signing deadlock risk detected", + "description": "This change may create a signing cycle between Safes and can permanently lock funds. You will not be allowed to proceed forward." + } + ], + "type": "array", + "items": { + "$ref": "#/components/schemas/DeadlockAnalysisResultDto" + } } } }, - "UpdateSpaceResponse": { + "CounterpartyAnalysisDto": { "type": "object", "properties": { - "uuid": { - "type": "string", - "description": "Space UUID" + "recipient": { + "type": "object", + "description": "Recipient analysis results mapped by address. Contains recipient interaction history and bridge analysis.type: Record
.", + "additionalProperties": { + "$ref": "#/components/schemas/RecipientAnalysisDto" + }, + "example": { + "0x0000000000000000000000000000000000000000": { + "isSafe": true, + "RECIPIENT_INTERACTION": [ + { + "severity": "INFO", + "type": "NEW_RECIPIENT", + "title": "New recipient", + "description": "This is the first time you are interacting with this recipient" + } + ] + } + } + }, + "contract": { + "type": "object", + "description": "Contract analysis results mapped by address. Contains contract verification, interaction history, and delegatecall analysis.type: Record.", + "additionalProperties": { + "$ref": "#/components/schemas/ContractAnalysisDto" + }, + "example": { + "0x0000000000000000000000000000000000000000": { + "CONTRACT_VERIFICATION": [ + { + "severity": "INFO", + "type": "VERIFIED", + "title": "Verified contract", + "description": "This contract has been verified and its source code is available" + } + ] + } + } + }, + "deadlock": { + "type": "object", + "description": "Deadlock analysis results mapped by Safe address. Contains signing deadlock risk findings for owner/threshold management transactions.", + "additionalProperties": { + "$ref": "#/components/schemas/DeadlockAnalysisDto" + }, + "example": { + "0x0000000000000000000000000000000000000000": { + "DEADLOCK": [ + { + "severity": "CRITICAL", + "type": "DEADLOCK_DETECTED", + "title": "Signing deadlock risk detected", + "description": "This change may create a signing cycle between Safes and can permanently lock funds. You will not be allowed to proceed forward." + } + ] + } + } } }, "required": [ - "uuid" + "recipient", + "contract", + "deadlock" ] }, - "SpaceAuditLogEntryDto": { + "PolicyConfigurationDto": { "type": "object", "properties": { - "id": { + "target": { "type": "string", - "description": "Monotonic entry id (bigint serialized as string)" + "description": "Contract the guarded call targets" }, - "eventType": { + "selector": { "type": "string", - "enum": [ - "SPACE_CREATED", - "SPACE_UPDATED", - "SPACE_DELETED", - "MEMBER_INVITED", - "MEMBER_INVITE_ACCEPTED", - "MEMBER_INVITE_DECLINED", - "MEMBER_INVITE_RENEWED", - "MEMBER_ROLE_UPDATED", - "MEMBER_ALIAS_UPDATED", - "MEMBER_REMOVED", - "MEMBER_LEFT", - "SAFE_ADDED", - "SAFE_REMOVED", - "ADDRESS_BOOK_UPSERTED", - "ADDRESS_BOOK_DELETED" - ] + "description": "4-byte function selector", + "example": "0xa9059cbb" }, - "actorUserId": { - "type": "number" + "operation": { + "type": "number", + "enum": [ + 0, + 1 + ], + "description": "0 = CALL, 1 = DELEGATECALL" }, - "actor": { + "policy": { "type": "string", - "description": "Resolved (and masked) display string of the acting user." + "description": "Policy contract to bind. The zero address removes the policy of this access." }, - "targetUser": { + "data": { "type": "string", - "nullable": true, - "description": "Resolved (and masked) display string of the affected user, when the event has one." - }, - "payload": { - "type": "object", - "description": "Event-specific payload, allowlisted per event type. Clients must treat every field as optional." - }, - "createdAt": { - "format": "date-time", - "type": "string" + "description": "Policy payload, abi-encoded as passed to the guard. At most 64 KiB (65,536 bytes)." } }, "required": [ - "id", - "eventType", - "actorUserId", - "actor", - "targetUser", - "payload", - "createdAt" + "target", + "selector", + "operation", + "policy", + "data" ] }, - "SpaceAuditLogPage": { + "CreatePolicyConfigurationRequestDto": { "type": "object", "properties": { - "count": { - "type": "number", - "nullable": true - }, - "next": { - "type": "string", - "nullable": true - }, - "previous": { + "root": { "type": "string", - "nullable": true + "description": "keccak256(abi.encode(Configuration[])), as requested on-chain" }, - "results": { + "configurations": { + "minItems": 1, + "maxItems": 100, "type": "array", "items": { - "$ref": "#/components/schemas/SpaceAuditLogEntryDto" + "$ref": "#/components/schemas/PolicyConfigurationDto" } } }, "required": [ - "results" - ] - }, - "SpaceAuditLogActorDto": { - "type": "object", - "properties": { - "actorUserId": { - "type": "number" - }, - "actor": { - "type": "string", - "description": "Resolved (and masked) display string of the actor." - } - }, - "required": [ - "actorUserId", - "actor" - ] - }, - "SpaceSafeDto": { - "type": "object", - "properties": { - "chainId": { - "type": "string" - }, - "address": { - "type": "string" - } - }, - "required": [ - "chainId", - "address" + "root", + "configurations" ] }, - "CreateSpaceSafesDto": { + "CreatePolicyConfigurationRequestResponse": { "type": "object", "properties": { - "safes": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SpaceSafeDto" - } + "root": { + "type": "string", + "description": "The stored configuration root" } }, "required": [ - "safes" + "root" ] }, - "GetSpaceSafeResponse": { + "ModuleEnforcementDto": { "type": "object", "properties": { - "safes": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - }, - "example": { - "{chainId}": [ - "0x..." - ] - } + "via": { + "type": "string", + "enum": [ + "module" + ] + }, + "moduleAddress": { + "type": "string", + "description": "The module enforcing the policy" } }, "required": [ - "safes" + "via", + "moduleAddress" ] }, - "DeleteSpaceSafesDto": { + "PolicyContractsDto": { "type": "object", "properties": { - "safes": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SpaceSafeDto" - } + "policyContract": { + "type": "string", + "description": "The policy implementation the guard delegates to" + }, + "safePolicyGuard": { + "type": "string", + "description": "The SafePolicyGuard deployment" } }, "required": [ - "safes" + "policyContract", + "safePolicyGuard" ] }, - "WalletInviteUserDto": { + "GuardSlotsDto": { "type": "object", "properties": { - "type": { + "transactionGuard": { + "$ref": "#/components/schemas/PolicyContractsDto" + }, + "moduleGuard": { + "$ref": "#/components/schemas/PolicyContractsDto" + } + } + }, + "PolicyAccessDto": { + "type": "object", + "properties": { + "target": { "type": "string", - "enum": [ - "wallet" - ] + "description": "The contract the governed calls target" }, - "address": { - "type": "string" + "selector": { + "type": "string", + "description": "The 4-byte function selector of the governed calls" }, - "role": { + "operation": { "type": "string", "enum": [ - "ADMIN", - "MEMBER" + "CALL", + "DELEGATECALL" ] - }, - "name": { - "type": "string", - "maxLength": 255 } }, "required": [ - "type", - "address", - "role", - "name" + "target", + "selector", + "operation" ] }, - "EmailInviteUserDto": { + "GuardEnforcementDto": { "type": "object", "properties": { - "type": { + "via": { "type": "string", "enum": [ - "email" + "guard" ] }, - "email": { - "type": "string", - "format": "email", - "maxLength": 255 + "guards": { + "$ref": "#/components/schemas/GuardSlotsDto" }, - "role": { - "type": "string", - "enum": [ - "ADMIN", - "MEMBER" + "access": { + "description": "The calls the guard applies the policy to", + "allOf": [ + { + "$ref": "#/components/schemas/PolicyAccessDto" + } ] - }, - "name": { - "type": "string", - "maxLength": 255 } }, "required": [ - "type", - "email", - "role", - "name" + "via", + "guards", + "access" ] }, - "InviteUsersDto": { + "OffChainEnforcementDto": { "type": "object", "properties": { - "users": { - "type": "array", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/WalletInviteUserDto" - }, - { - "$ref": "#/components/schemas/EmailInviteUserDto" - } - ] - } + "via": { + "type": "string", + "enum": [ + "offchain" + ], + "description": "Nothing on chain enforces the policy, so it is access rather than an audited restriction" + }, + "source": { + "type": "string", + "enum": [ + "delegates" + ], + "description": "Where the grant is held" } }, "required": [ - "users" + "via", + "source" ] }, - "Invitation": { + "NativeTokenMetadataDto": { "type": "object", "properties": { - "userId": { + "address": { + "type": "string" + }, + "decimals": { "type": "number" }, + "logoUri": { + "type": "string" + }, "name": { "type": "string" }, - "spaceUuid": { - "type": "string", - "description": "Space UUID" + "symbol": { + "type": "string" }, - "role": { - "type": "string", - "enum": [ - "ADMIN", - "MEMBER" - ] + "trusted": { + "type": "boolean", + "description": "Whether the Transaction Service lists the token in one of its imported token lists" }, - "status": { + "type": { "type": "string", "enum": [ - "INVITED", - "ACTIVE", - "DECLINED" + "NATIVE_TOKEN" ] - }, - "invitedBy": { - "type": "number", - "nullable": true } }, "required": [ - "userId", + "address", + "decimals", + "logoUri", "name", - "spaceUuid", - "role", - "status", - "invitedBy" - ] - }, - "AcceptInviteDto": { - "type": "object", - "properties": { - "name": { - "type": "string", - "maxLength": 255 - } - }, - "required": [ - "name" + "symbol", + "trusted", + "type" ] }, - "MemberUser": { + "Erc20TokenMetadataDto": { "type": "object", "properties": { - "id": { + "address": { + "type": "string" + }, + "decimals": { "type": "number" }, - "status": { + "logoUri": { + "type": "string" + }, + "name": { + "type": "string" + }, + "symbol": { + "type": "string" + }, + "trusted": { + "type": "boolean", + "description": "Whether the Transaction Service lists the token in one of its imported token lists" + }, + "type": { "type": "string", "enum": [ - "PENDING", - "ACTIVE" + "ERC20" ] - }, - "email": { - "type": "string", - "nullable": true } }, "required": [ - "id", - "status", - "email" + "address", + "decimals", + "logoUri", + "name", + "symbol", + "trusted", + "type" ] }, - "MemberDto": { + "SpendingLimitAllowanceDto": { "type": "object", "properties": { - "id": { - "type": "number" - }, - "role": { + "tokenAddress": { "type": "string", - "enum": [ - "ADMIN", - "MEMBER" - ] + "description": "The token the limit applies to; zero address for native" }, - "status": { - "type": "string", - "enum": [ - "INVITED", - "ACTIVE", - "DECLINED" - ] + "tokenMetadata": { + "oneOf": [ + { + "$ref": "#/components/schemas/NativeTokenMetadataDto" + }, + { + "$ref": "#/components/schemas/Erc20TokenMetadataDto" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "NATIVE_TOKEN": "#/components/schemas/NativeTokenMetadataDto", + "ERC20": "#/components/schemas/Erc20TokenMetadataDto" + } + }, + "nullable": true, + "description": "Metadata of `tokenAddress`; null when it could not be resolved" }, - "name": { - "type": "string" + "amount": { + "type": "string", + "description": "Per-window ceiling, in base units" }, - "alias": { + "spent": { "type": "string", - "nullable": true + "description": "Spent in the current window, in base units" }, - "invitedBy": { + "resetPeriodMinutes": { "type": "number", - "nullable": true + "description": "Window length in minutes; 0 never resets" }, - "inviteExpiresAt": { - "format": "date-time", - "type": "string", - "nullable": true + "resetsAtMinute": { + "type": "number", + "nullable": true, + "description": "Minutes since the epoch of the next reset, the unit the module counts windows in; null when it never resets" }, - "createdAt": { - "format": "date-time", - "type": "string" + "resetBoundaryIsExact": { + "type": "boolean", + "description": "False when the reset boundary could not be recovered exactly, so `resetsAtMinute` may be up to one period out. `amount` is unaffected." }, - "updatedAt": { - "format": "date-time", - "type": "string" + "isDelegateActive": { + "type": "boolean", + "description": "False when the spender's delegate registration was removed: nothing is spendable now, but the allowance returns to effect if the delegate is re-added" }, - "user": { - "$ref": "#/components/schemas/MemberUser" + "createdAt": { + "type": "number", + "description": "Unix seconds this allowance was (re-)established" + }, + "updatedAt": { + "type": "number", + "description": "Unix seconds of the last event that changed this allowance" } }, "required": [ - "id", - "role", - "status", - "name", - "invitedBy", + "tokenAddress", + "tokenMetadata", + "amount", + "spent", + "resetPeriodMinutes", + "resetsAtMinute", + "resetBoundaryIsExact", + "isDelegateActive", "createdAt", - "updatedAt", - "user" + "updatedAt" ] }, - "MembersDto": { + "SpendingLimitSpenderDto": { "type": "object", "properties": { - "members": { + "spender": { + "type": "string", + "description": "Name resolved by the client, never carried here" + }, + "isActive": { + "type": "boolean", + "description": "False when the spender is deregistered: nothing is spendable now, but the allowances survive and return if it is re-added" + }, + "allowances": { "type": "array", "items": { - "$ref": "#/components/schemas/MemberDto" + "$ref": "#/components/schemas/SpendingLimitAllowanceDto" } } }, "required": [ - "members" + "spender", + "isActive", + "allowances" ] }, - "UpdateRoleDto": { + "SpendingLimitPolicyDataDto": { "type": "object", "properties": { - "role": { + "module": { "type": "string", - "enum": [ - "ADMIN", - "MEMBER" - ] + "description": "The allowance module holding this state" + }, + "spenders": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SpendingLimitSpenderDto" + } } }, "required": [ - "role" + "module", + "spenders" ] }, - "UpdateMemberAliasDto": { + "ProposerGrantDto": { "type": "object", "properties": { - "alias": { + "delegator": { "type": "string", - "description": "The new alias for the member" + "description": "The owner that granted the proposer" + }, + "label": { + "type": "string", + "description": "The label this owner gave the proposer; empty when unlabelled" } }, "required": [ - "alias" + "delegator", + "label" ] }, - "CounterfactualSafeDto": { + "ProposerDto": { "type": "object", "properties": { - "chainId": { - "type": "string" - }, - "address": { - "type": "string" - }, - "factoryAddress": { - "type": "string" - }, - "masterCopy": { - "type": "string" - }, - "saltNonce": { - "type": "string" - }, - "safeVersion": { - "type": "string" - }, - "threshold": { - "type": "number" + "proposer": { + "type": "string", + "description": "The address allowed to propose transactions" }, - "owners": { + "delegatedBy": { + "description": "The owners that granted it, each with the label they gave. The label is stored per grant, so two owners can label the same proposer differently", "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/ProposerGrantDto" } - }, - "fallbackHandler": { - "type": "string", - "nullable": true - }, - "to": { - "type": "string", - "nullable": true - }, - "data": { - "type": "string" - }, - "paymentToken": { - "type": "string", - "nullable": true - }, - "payment": { - "type": "string", - "nullable": true - }, - "paymentReceiver": { - "type": "string", - "nullable": true } }, "required": [ - "chainId", - "address", - "factoryAddress", - "masterCopy", - "saltNonce", - "safeVersion", - "threshold", - "owners", - "data" + "proposer", + "delegatedBy" ] }, - "CreateCounterfactualSafesDto": { + "ProposerPolicyDataDto": { "type": "object", "properties": { - "safes": { + "proposers": { "type": "array", "items": { - "$ref": "#/components/schemas/CounterfactualSafeDto" + "$ref": "#/components/schemas/ProposerDto" } } }, "required": [ - "safes" + "proposers" ] }, - "GetCounterfactualSafeItem": { + "Erc20TransferRecipientDto": { "type": "object", "properties": { - "address": { - "type": "string" - }, - "factoryAddress": { - "type": "string" - }, - "masterCopy": { - "type": "string" - }, - "saltNonce": { - "type": "string" - }, - "safeVersion": { - "type": "string" - }, - "threshold": { - "type": "number" - }, - "owners": { - "type": "array", - "items": { - "type": "string" - } - }, - "fallbackHandler": { - "type": "string", - "nullable": true - }, - "to": { - "type": "string", - "nullable": true - }, - "data": { - "type": "string" - }, - "paymentToken": { - "type": "string", - "nullable": true - }, - "payment": { + "account": { "type": "string", - "nullable": true + "description": "An address the Safe can send this token to" }, - "paymentReceiver": { + "permission": { "type": "string", - "nullable": true + "enum": [ + "ONCE", + "ALWAYS" + ] } }, "required": [ - "address", - "factoryAddress", - "masterCopy", - "saltNonce", - "safeVersion", - "threshold", - "owners", - "fallbackHandler", - "to", - "data", - "paymentToken", - "payment", - "paymentReceiver" + "account", + "permission" ] }, - "GetCounterfactualSafesResponse": { + "Erc20TransferPolicyDataDto": { "type": "object", "properties": { - "safes": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GetCounterfactualSafeItem" + "tokenAddress": { + "type": "string", + "description": "The ERC20 token the allowlist applies to" + }, + "tokenMetadata": { + "oneOf": [ + { + "$ref": "#/components/schemas/NativeTokenMetadataDto" + }, + { + "$ref": "#/components/schemas/Erc20TokenMetadataDto" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "NATIVE_TOKEN": "#/components/schemas/NativeTokenMetadataDto", + "ERC20": "#/components/schemas/Erc20TokenMetadataDto" } }, - "example": { - "{chainId}": [ - { - "address": "0x...", - "factoryAddress": "0x...", - "masterCopy": "0x...", - "saltNonce": "1712000000000", - "safeVersion": "1.4.1", - "threshold": 1, - "owners": [ - "0x..." - ], - "fallbackHandler": "0x...", - "to": null, - "data": "0x...", - "paymentToken": null, - "payment": null, - "paymentReceiver": null - } - ] + "nullable": true, + "description": "Metadata of `tokenAddress`; null when it could not be resolved" + }, + "recipients": { + "description": "The recipients of the token transfers the policy permits", + "type": "array", + "items": { + "$ref": "#/components/schemas/Erc20TransferRecipientDto" } } }, "required": [ - "safes" + "tokenAddress", + "tokenMetadata", + "recipients" ] }, - "DeleteCounterfactualSafeDto": { + "CosignerPolicyDataDto": { + "type": "object", + "properties": { + "cosignerAddress": { + "type": "string", + "description": "The cosigner the policy enforces." + } + }, + "required": [ + "cosignerAddress" + ] + }, + "StatelessPolicyDataDto": { + "type": "object", + "properties": {} + }, + "SafeRefDto": { "type": "object", "properties": { "chainId": { @@ -10481,1402 +13341,1613 @@ } }, "required": [ - "chainId", - "address" + "chainId", + "address" + ] + }, + "ActivePolicyDto": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "spending-limit", + "recovery", + "proposer", + "erc20-transfer", + "cosigner", + "allow", + "native-transfer", + "deny", + "multisend" + ] + }, + "enforcement": { + "oneOf": [ + { + "$ref": "#/components/schemas/ModuleEnforcementDto" + }, + { + "$ref": "#/components/schemas/GuardEnforcementDto" + }, + { + "$ref": "#/components/schemas/OffChainEnforcementDto" + } + ], + "discriminator": { + "propertyName": "via", + "mapping": { + "module": "#/components/schemas/ModuleEnforcementDto", + "guard": "#/components/schemas/GuardEnforcementDto", + "offchain": "#/components/schemas/OffChainEnforcementDto" + } + } + }, + "enabled": { + "type": "boolean", + "description": "False when the policy is configured but not enforced" + }, + "data": { + "oneOf": [ + { + "$ref": "#/components/schemas/SpendingLimitPolicyDataDto" + }, + { + "$ref": "#/components/schemas/ProposerPolicyDataDto" + }, + { + "$ref": "#/components/schemas/Erc20TransferPolicyDataDto" + }, + { + "$ref": "#/components/schemas/CosignerPolicyDataDto" + }, + { + "$ref": "#/components/schemas/StatelessPolicyDataDto" + } + ] + }, + "safe": { + "description": "The Safe the policy is in effect on", + "allOf": [ + { + "$ref": "#/components/schemas/SafeRefDto" + } + ] + } + }, + "required": [ + "type", + "enforcement", + "enabled", + "data", + "safe" ] }, - "DeleteCounterfactualSafesDto": { + "EnableModuleChangeDto": { "type": "object", "properties": { - "safes": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DeleteCounterfactualSafeDto" - } + "kind": { + "type": "string", + "enum": [ + "enable-module" + ] } }, "required": [ - "safes" + "kind" ] }, - "SurveyOptionDto": { + "AddDelegateChangeDto": { "type": "object", "properties": { - "key": { - "type": "string" - }, - "label": { - "type": "string" - }, - "description": { - "type": "string" + "kind": { + "type": "string", + "enum": [ + "add-delegate" + ] }, - "icon": { - "type": "string" + "delegate": { + "type": "string", + "description": "The address being added as a delegate in AllowanceModule contract" } }, "required": [ - "key", - "label" + "kind", + "delegate" ] }, - "SurveyPageDto": { + "RemoveDelegateChangeDto": { "type": "object", "properties": { - "id": { - "type": "string" - }, - "title": { - "type": "string" - }, - "subtitle": { + "kind": { "type": "string", - "nullable": true + "enum": [ + "remove-delegate" + ] }, - "multiSelect": { - "type": "boolean" + "delegate": { + "type": "string", + "description": "The delegate being removed" }, - "options": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SurveyOptionDto" - } - } - }, - "required": [ - "id", - "title", - "subtitle", - "multiSelect", - "options" - ] - }, - "SurveyContentDto": { - "type": "object", - "properties": { - "pages": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SurveyPageDto" - } + "removeAllowances": { + "type": "boolean", + "description": "Whether the delegate's allowances are deleted along with it" } }, "required": [ - "pages" + "kind", + "delegate", + "removeAllowances" ] }, - "SurveyDto": { + "SetAllowanceChangeDto": { "type": "object", "properties": { - "id": { - "type": "number" + "kind": { + "type": "string", + "enum": [ + "set-allowance" + ] }, - "slug": { + "delegate": { "type": "string" }, - "version": { - "type": "number" + "token": { + "type": "string", + "description": "The token the limit applies to; zero address for native" }, - "title": { - "type": "string" + "tokenMetadata": { + "oneOf": [ + { + "$ref": "#/components/schemas/NativeTokenMetadataDto" + }, + { + "$ref": "#/components/schemas/Erc20TokenMetadataDto" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "NATIVE_TOKEN": "#/components/schemas/NativeTokenMetadataDto", + "ERC20": "#/components/schemas/Erc20TokenMetadataDto" + } + }, + "nullable": true, + "description": "Metadata of `token`; null when it could not be resolved" }, - "subtitle": { + "amount": { "type": "string", - "nullable": true + "description": "Per-window ceiling, in base units" }, - "surveyContent": { - "$ref": "#/components/schemas/SurveyContentDto" + "resetPeriodMinutes": { + "type": "number", + "description": "Window length in minutes; 0 never resets" } }, "required": [ - "id", - "slug", - "version", - "title", - "subtitle", - "surveyContent" + "kind", + "delegate", + "token", + "tokenMetadata", + "amount", + "resetPeriodMinutes" ] }, - "SpaceSurveyResponseDto": { + "ResetAllowanceChangeDto": { "type": "object", "properties": { - "surveyVersion": { - "type": "number" - }, - "selections": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - }, - "description": "Map from page id → selected option keys" + "kind": { + "type": "string", + "enum": [ + "reset-allowance" + ] }, - "submittedAt": { - "format": "date-time", + "delegate": { "type": "string" }, - "updatedAt": { - "format": "date-time", + "token": { "type": "string" }, - "answeredByUserId": { - "type": "number", - "nullable": true + "tokenMetadata": { + "oneOf": [ + { + "$ref": "#/components/schemas/NativeTokenMetadataDto" + }, + { + "$ref": "#/components/schemas/Erc20TokenMetadataDto" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "NATIVE_TOKEN": "#/components/schemas/NativeTokenMetadataDto", + "ERC20": "#/components/schemas/Erc20TokenMetadataDto" + } + }, + "nullable": true, + "description": "Metadata of `token`; null when it could not be resolved" } }, "required": [ - "surveyVersion", - "selections", - "submittedAt", - "updatedAt", - "answeredByUserId" + "kind", + "delegate", + "token", + "tokenMetadata" ] }, - "SurveyStateDto": { + "DeleteAllowanceChangeDto": { "type": "object", "properties": { - "survey": { - "$ref": "#/components/schemas/SurveyDto" + "kind": { + "type": "string", + "enum": [ + "delete-allowance" + ] }, - "surveyResponse": { - "nullable": true, - "type": "object", - "allOf": [ + "delegate": { + "type": "string" + }, + "token": { + "type": "string" + }, + "tokenMetadata": { + "oneOf": [ { - "$ref": "#/components/schemas/SpaceSurveyResponseDto" + "$ref": "#/components/schemas/NativeTokenMetadataDto" + }, + { + "$ref": "#/components/schemas/Erc20TokenMetadataDto" } - ] - } - }, - "required": [ - "survey", - "surveyResponse" - ] - }, - "SubmitSurveyResponseDto": { - "type": "object", - "properties": { - "selections": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "NATIVE_TOKEN": "#/components/schemas/NativeTokenMetadataDto", + "ERC20": "#/components/schemas/Erc20TokenMetadataDto" } }, - "description": "Map from page id → selected option keys", - "example": { - "use_cases": [ - "run_payments", - "hold_assets" - ] - } + "nullable": true, + "description": "Metadata of `token`; null when it could not be resolved" } }, "required": [ - "selections" + "kind", + "delegate", + "token", + "tokenMetadata" ] }, - "SurveyResponseResultDto": { + "PendingSpendingLimitDataDto": { "type": "object", "properties": { - "id": { - "type": "number" - }, - "spaceUuid": { + "module": { "type": "string", - "description": "Space UUID" - }, - "surveySlug": { - "type": "string" - }, - "surveyVersion": { - "type": "number" - }, - "selections": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "submittedAt": { - "format": "date-time", - "type": "string" - }, - "updatedAt": { - "format": "date-time", - "type": "string" + "description": "The AllowanceModule deployment holding this state" }, - "answeredByUserId": { - "type": "number", - "nullable": true + "changes": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/EnableModuleChangeDto" + }, + { + "$ref": "#/components/schemas/AddDelegateChangeDto" + }, + { + "$ref": "#/components/schemas/RemoveDelegateChangeDto" + }, + { + "$ref": "#/components/schemas/SetAllowanceChangeDto" + }, + { + "$ref": "#/components/schemas/ResetAllowanceChangeDto" + }, + { + "$ref": "#/components/schemas/DeleteAllowanceChangeDto" + } + ], + "discriminator": { + "propertyName": "kind", + "mapping": { + "enable-module": "#/components/schemas/EnableModuleChangeDto", + "add-delegate": "#/components/schemas/AddDelegateChangeDto", + "remove-delegate": "#/components/schemas/RemoveDelegateChangeDto", + "set-allowance": "#/components/schemas/SetAllowanceChangeDto", + "reset-allowance": "#/components/schemas/ResetAllowanceChangeDto", + "delete-allowance": "#/components/schemas/DeleteAllowanceChangeDto" + } + } + }, + "description": "The AllowanceModule calls this transaction decodes to" } }, "required": [ - "id", - "spaceUuid", - "surveySlug", - "surveyVersion", - "selections", - "submittedAt", - "updatedAt", - "answeredByUserId" + "module", + "changes" ] }, - "FeatureKey": { - "type": "string", - "enum": [ - "safe_seats" - ], - "description": "Feature key from the entitlements catalog." - }, - "BinaryEntitlement": { + "PendingPolicyDto": { "type": "object", "properties": { - "feature": { - "description": "Feature key from the entitlements catalog.", - "allOf": [ - { - "$ref": "#/components/schemas/FeatureKey" - } + "kind": { + "type": "string", + "enum": [ + "queued-transaction" ] }, - "enabled": { - "type": "boolean", - "description": "Whether the plan grants the feature at all. A metered feature reports its quota and usage even when this is false." - }, "type": { "type": "string", "enum": [ - "binary" + "spending-limit" + ] + }, + "enforcement": { + "$ref": "#/components/schemas/ModuleEnforcementDto" + }, + "safeTxHash": { + "type": "string", + "description": "The queued transaction this change was found in" + }, + "nonce": { + "type": "number" + }, + "confirmations": { + "type": "number" + }, + "confirmationsRequired": { + "type": "number" + }, + "proposedAt": { + "type": "number", + "description": "Unix seconds the transaction was proposed at" + }, + "proposer": { + "type": "string", + "nullable": true, + "description": "The owner or delegate who proposed the transaction, if known" + }, + "data": { + "$ref": "#/components/schemas/PendingSpendingLimitDataDto" + }, + "safe": { + "description": "The Safe the change is queued on", + "allOf": [ + { + "$ref": "#/components/schemas/SafeRefDto" + } ] } }, "required": [ - "feature", - "enabled", - "type" + "kind", + "type", + "enforcement", + "safeTxHash", + "nonce", + "confirmations", + "confirmationsRequired", + "proposedAt", + "proposer", + "data", + "safe" ] }, - "ValueEntitlement": { + "SetGuardChangeDto": { "type": "object", "properties": { - "feature": { - "description": "Feature key from the entitlements catalog.", - "allOf": [ - { - "$ref": "#/components/schemas/FeatureKey" - } - ] - }, - "enabled": { - "type": "boolean", - "description": "Whether the plan grants the feature at all. A metered feature reports its quota and usage even when this is false." - }, - "type": { + "kind": { "type": "string", "enum": [ - "value" + "set-guard" ] }, - "value": { + "from": { "type": "string", - "nullable": true + "nullable": true, + "description": "The transaction guard before this call; null for none" + }, + "to": { + "type": "string", + "nullable": true, + "description": "The transaction guard after this call; null removes it" } }, "required": [ - "feature", - "enabled", - "type", - "value" + "kind", + "from", + "to" ] }, - "MeteredEntitlement": { + "SetModuleGuardChangeDto": { "type": "object", "properties": { - "feature": { - "description": "Feature key from the entitlements catalog.", - "allOf": [ - { - "$ref": "#/components/schemas/FeatureKey" - } - ] - }, - "enabled": { - "type": "boolean", - "description": "Whether the plan grants the feature at all. A metered feature reports its quota and usage even when this is false." - }, - "type": { + "kind": { "type": "string", "enum": [ - "metered" + "set-module-guard" ] }, - "quota": { - "type": "number", + "from": { + "type": "string", "nullable": true, - "description": "The plan's quota, never inflated to match usage; null means unlimited." - }, - "used": { - "type": "number", - "description": "May legally exceed `quota`." + "description": "The module guard before this call; null for none" }, - "resetsAt": { - "format": "date-time", + "to": { "type": "string", "nullable": true, - "description": "Null for stock-type features (seats) that have no reset window." + "description": "The module guard after this call; null removes it" } }, "required": [ - "feature", - "enabled", - "type", - "quota", - "used", - "resetsAt" + "kind", + "from", + "to" ] }, - "EntitlementsPlan": { + "PendingTransactionDto": { "type": "object", "properties": { - "id": { - "type": "string", - "description": "Plan identifier in the billing service" + "safeTxHash": { + "type": "string" }, - "name": { - "type": "string", - "nullable": true + "nonce": { + "type": "number" }, - "cycleEndsAt": { - "format": "date-time", + "confirmations": { + "type": "number" + }, + "confirmationsRequired": { + "type": "number" + }, + "proposedAt": { + "type": "number", + "description": "Unix seconds the transaction was proposed at" + }, + "proposer": { "type": "string", "nullable": true, - "description": "End of the current billing cycle" + "description": "The owner or delegate who proposed the transaction, if known" } }, "required": [ - "id", - "name", - "cycleEndsAt" + "safeTxHash", + "nonce", + "confirmations", + "confirmationsRequired", + "proposedAt", + "proposer" ] }, - "EntitlementsResponse": { + "PendingGuardInstallationDto": { "type": "object", "properties": { - "plan": { - "nullable": true, - "description": "Null when the workspace has no active subscription.", - "type": "object", + "kind": { + "type": "string", + "enum": [ + "guard-installation" + ] + }, + "status": { + "type": "string", + "enum": [ + "in-signing", + "ready" + ] + }, + "safe": { + "description": "The Safe the transaction is queued on", "allOf": [ { - "$ref": "#/components/schemas/EntitlementsPlan" + "$ref": "#/components/schemas/SafeRefDto" } ] }, - "entitlements": { + "changes": { "type": "array", - "description": "One entry per catalog feature. Which fields an entry carries is decided by `type`: a metered one always carries quota, usage and its reset window, and the others never do.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/BinaryEntitlement" - }, - { - "$ref": "#/components/schemas/ValueEntitlement" + "$ref": "#/components/schemas/SetGuardChangeDto" }, { - "$ref": "#/components/schemas/MeteredEntitlement" + "$ref": "#/components/schemas/SetModuleGuardChangeDto" } ], "discriminator": { - "propertyName": "type", + "propertyName": "kind", "mapping": { - "binary": "#/components/schemas/BinaryEntitlement", - "value": "#/components/schemas/ValueEntitlement", - "metered": "#/components/schemas/MeteredEntitlement" + "set-guard": "#/components/schemas/SetGuardChangeDto", + "set-module-guard": "#/components/schemas/SetModuleGuardChangeDto" } } + }, + "description": "The guard installation calls of the transaction, in calldata order" + }, + "transaction": { + "$ref": "#/components/schemas/PendingTransactionDto" + } + }, + "required": [ + "kind", + "status", + "safe", + "changes", + "transaction" + ] + }, + "PendingImmediateGuardPoliciesDto": { + "type": "object", + "properties": { + "kind": { + "type": "string", + "enum": [ + "immediate-guard-policies" + ] + }, + "status": { + "type": "string", + "enum": [ + "in-signing", + "ready" + ] + }, + "safe": { + "description": "The Safe the transaction is queued on", + "allOf": [ + { + "$ref": "#/components/schemas/SafeRefDto" + } + ] + }, + "guard": { + "type": "string", + "description": "The SafePolicyGuard the policies are bound on" + }, + "configurations": { + "description": "The configurations configureImmediately binds", + "type": "array", + "items": { + "$ref": "#/components/schemas/PolicyConfigurationDto" } + }, + "transaction": { + "$ref": "#/components/schemas/PendingTransactionDto" } }, "required": [ - "plan", - "entitlements" + "kind", + "status", + "safe", + "guard", + "configurations", + "transaction" ] }, - "SafeList": { + "PendingDelayedGuardPoliciesDto": { "type": "object", "properties": { - "safes": { + "kind": { + "type": "string", + "enum": [ + "delayed-guard-policies" + ] + }, + "status": { + "type": "string", + "enum": [ + "draft", + "configuration-in-signing", + "pending-application", + "application-in-signing", + "application-ready", + "expired" + ], + "description": "draft: stored in CGW, no transaction in signing yet. configuration-in-signing: requestConfiguration is queued. pending-application: requested, waiting for or past readyAt. application-in-signing: applyConfiguration is queued and collecting signatures. application-ready: applyConfiguration is signed and can execute. expired: the application window has closed." + }, + "safe": { + "description": "The Safe the configuration belongs to", + "allOf": [ + { + "$ref": "#/components/schemas/SafeRefDto" + } + ] + }, + "guard": { + "type": "string", + "nullable": true, + "description": "The SafePolicyGuard of the root; null for a draft" + }, + "root": { + "type": "string", + "description": "keccak256(abi.encode(Configuration[]))" + }, + "configurations": { + "nullable": true, + "description": "The configurations behind the root; null when CGW does not know them", "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/PolicyConfigurationDto" } + }, + "readyAt": { + "type": "number", + "nullable": true, + "description": "Unix seconds applyConfiguration is valid from; null until the root is requested on-chain" + }, + "expiresAt": { + "type": "number", + "nullable": true, + "description": "Unix seconds the application window closes; null until the root is requested on-chain" + }, + "transaction": { + "nullable": true, + "description": "The queued request or apply transaction, if any", + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/PendingTransactionDto" + } + ] + }, + "createdAt": { + "type": "number", + "nullable": true, + "description": "Unix seconds the change was first seen: when CGW stored its configurations, else when its queued transaction was proposed. Null for a root requested outside the wallet." } }, "required": [ - "safes" + "kind", + "status", + "safe", + "guard", + "root", + "configurations", + "readyAt", + "expiresAt", + "transaction", + "createdAt" ] }, - "RelayDto": { + "SurveyOptionDto": { "type": "object", "properties": { - "version": { + "key": { "type": "string" }, - "to": { + "label": { "type": "string" }, - "data": { + "description": { "type": "string" }, - "gasLimit": { - "type": "string", - "nullable": true, - "description": "Accepted for backward compatibility and validation; not forwarded to the relay provider." - }, - "safeTxHash": { - "type": "string", - "description": "Safe transaction hash for relay-fee eligibility check" - }, - "acceptUnverifiedSimulation": { - "type": "boolean", - "description": "Set to true to proceed with the relay when a previous attempt returned INDETERMINATE_SIMULATION. The user has acknowledged the simulation could not be completed and accepts the risk." - } - }, - "required": [ - "version", - "to", - "data" - ] - }, - "Relay": { - "type": "object", - "properties": { - "taskId": { + "icon": { "type": "string" } }, "required": [ - "taskId" + "key", + "label" ] }, - "RelayErrorResponse": { + "SurveyPageDto": { "type": "object", "properties": { - "code": { - "type": "string", - "enum": [ - "SIMULATION_FAILED", - "INDETERMINATE_SIMULATION" - ], - "description": "Stable identifier of the error condition. The frontend MUST branch on this value (not on `message`, which is informational and may change)." + "id": { + "type": "string" }, - "message": { - "type": "string", - "description": "Human-readable description of the error. Informational only; do not parse." + "title": { + "type": "string" }, - "statusCode": { - "type": "number", - "example": 422 - } - }, - "required": [ - "code", - "message", - "statusCode" - ] - }, - "RelayTaskStatusReceipt": { - "type": "object", - "properties": { - "transactionHash": { + "subtitle": { "type": "string", - "example": "0x4e4bb4493b2183061c3a0106ea96604edcc84f83313dbc0ab718abb1523d1042" + "nullable": true + }, + "multiSelect": { + "type": "boolean" + }, + "options": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SurveyOptionDto" + } } }, "required": [ - "transactionHash" + "id", + "title", + "subtitle", + "multiSelect", + "options" ] }, - "RelayTaskStatus": { + "SurveyContentDto": { "type": "object", "properties": { - "status": { - "type": "number", - "description": "Relay task status code: 100=Pending, 110=Submitted, 200=Included, 400=Rejected, 500=Reverted", - "enum": [ - 100, - 110, - 200, - 400, - 500 - ], - "example": 200 - }, - "receipt": { - "description": "On-chain receipt. Only present when status is 200 (Included) or 500 (Reverted)", - "allOf": [ - { - "$ref": "#/components/schemas/RelayTaskStatusReceipt" - } - ] + "pages": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SurveyPageDto" + } } }, "required": [ - "status" + "pages" ] }, - "RelaysRemaining": { + "SurveyDto": { "type": "object", "properties": { - "remaining": { + "id": { "type": "number" }, - "limit": { + "slug": { + "type": "string" + }, + "version": { "type": "number" + }, + "title": { + "type": "string" + }, + "subtitle": { + "type": "string", + "nullable": true + }, + "surveyContent": { + "$ref": "#/components/schemas/SurveyContentDto" } }, "required": [ - "remaining", - "limit" + "id", + "slug", + "version", + "title", + "subtitle", + "surveyContent" ] }, - "SafeAppProvider": { + "SpaceSurveyResponseDto": { "type": "object", "properties": { - "url": { + "surveyVersion": { + "type": "number" + }, + "selections": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Map from page id → selected option keys" + }, + "submittedAt": { + "format": "date-time", "type": "string" }, - "name": { + "updatedAt": { + "format": "date-time", "type": "string" + }, + "answeredByUserId": { + "type": "number", + "nullable": true } }, "required": [ - "url", - "name" + "surveyVersion", + "selections", + "submittedAt", + "updatedAt", + "answeredByUserId" ] }, - "SafeAppAccessControl": { + "SurveyStateDto": { "type": "object", "properties": { - "type": { - "type": "string" + "survey": { + "$ref": "#/components/schemas/SurveyDto" }, - "value": { + "surveyResponse": { "nullable": true, - "type": "array", - "items": { - "type": "string" - } + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/SpaceSurveyResponseDto" + } + ] } }, "required": [ - "type" + "survey", + "surveyResponse" ] }, - "SafeAppSocialProfile": { + "SubmitSurveyResponseDto": { "type": "object", "properties": { - "platform": { - "type": "string", - "enum": [ - "DISCORD", - "GITHUB", - "TWITTER", - "TELEGRAM", - "UNKNOWN" - ] - }, - "url": { - "type": "string" + "selections": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Map from page id → selected option keys", + "example": { + "use_cases": [ + "run_payments", + "hold_assets" + ] + } } }, "required": [ - "platform", - "url" + "selections" ] }, - "SafeApp": { + "SurveyResponseResultDto": { "type": "object", "properties": { "id": { "type": "number" }, - "url": { - "type": "string" - }, - "name": { - "type": "string" - }, - "iconUrl": { + "spaceUuid": { "type": "string", - "nullable": true + "description": "Space UUID" }, - "description": { + "surveySlug": { "type": "string" }, - "chainIds": { - "type": "array", - "items": { - "type": "string" - } + "surveyVersion": { + "type": "number" }, - "provider": { - "nullable": true, + "selections": { "type": "object", - "allOf": [ - { - "$ref": "#/components/schemas/SafeAppProvider" + "additionalProperties": { + "type": "array", + "items": { + "type": "string" } - ] - }, - "accessControl": { - "$ref": "#/components/schemas/SafeAppAccessControl" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - } - }, - "features": { - "type": "array", - "items": { - "type": "string" } }, - "developerWebsite": { - "type": "string", - "nullable": true + "submittedAt": { + "format": "date-time", + "type": "string" }, - "socialProfiles": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SafeAppSocialProfile" - } + "updatedAt": { + "format": "date-time", + "type": "string" }, - "featured": { - "type": "boolean" + "answeredByUserId": { + "type": "number", + "nullable": true } }, "required": [ "id", - "url", - "name", - "description", - "chainIds", - "accessControl", - "tags", - "features", - "socialProfiles", - "featured" + "spaceUuid", + "surveySlug", + "surveyVersion", + "selections", + "submittedAt", + "updatedAt", + "answeredByUserId" ] }, - "SafeState": { + "FeatureKey": { + "type": "string", + "enum": [ + "safe_seats", + "copilot_scans", + "sponsored_transactions", + "policies", + "safenet_checks" + ], + "description": "Feature key from the entitlements catalog." + }, + "BinaryEntitlement": { "type": "object", "properties": { - "address": { - "$ref": "#/components/schemas/AddressInfo" - }, - "chainId": { - "type": "string" - }, - "nonce": { - "type": "number" - }, - "threshold": { - "type": "number" - }, - "owners": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AddressInfo" - } - }, - "implementation": { - "$ref": "#/components/schemas/AddressInfo" - }, - "modules": { - "nullable": true, - "type": "array", - "items": { - "$ref": "#/components/schemas/AddressInfo" - } - }, - "fallbackHandler": { - "nullable": true, - "type": "object", + "feature": { + "description": "Feature key from the entitlements catalog.", "allOf": [ { - "$ref": "#/components/schemas/AddressInfo" + "$ref": "#/components/schemas/FeatureKey" } ] }, - "guard": { - "nullable": true, - "type": "object", + "enabled": { + "type": "boolean", + "description": "Whether the plan grants the feature at all. A metered feature reports its quota and usage even when this is false." + }, + "type": { + "type": "string", + "enum": [ + "binary" + ] + } + }, + "required": [ + "feature", + "enabled", + "type" + ] + }, + "ValueEntitlement": { + "type": "object", + "properties": { + "feature": { + "description": "Feature key from the entitlements catalog.", "allOf": [ { - "$ref": "#/components/schemas/AddressInfo" + "$ref": "#/components/schemas/FeatureKey" } ] }, - "version": { - "type": "string", - "nullable": true + "enabled": { + "type": "boolean", + "description": "Whether the plan grants the feature at all. A metered feature reports its quota and usage even when this is false." }, - "implementationVersionState": { + "type": { "type": "string", "enum": [ - "UP_TO_DATE", - "OUTDATED", - "UNKNOWN" + "value" ] }, - "collectiblesTag": { + "value": { "type": "string", "nullable": true + } + }, + "required": [ + "feature", + "enabled", + "type", + "value" + ] + }, + "MeteredEntitlement": { + "type": "object", + "properties": { + "feature": { + "description": "Feature key from the entitlements catalog.", + "allOf": [ + { + "$ref": "#/components/schemas/FeatureKey" + } + ] }, - "txQueuedTag": { + "enabled": { + "type": "boolean", + "description": "Whether the plan grants the feature at all. A metered feature reports its quota and usage even when this is false." + }, + "type": { "type": "string", - "nullable": true + "enum": [ + "metered" + ] }, - "txHistoryTag": { + "quota": { + "type": "number", + "nullable": true, + "description": "The plan's quota, never inflated to match usage; null means unlimited." + }, + "used": { + "type": "number", + "description": "May legally exceed `quota`." + }, + "resetsAt": { + "format": "date-time", "type": "string", - "nullable": true + "nullable": true, + "description": "Null for stock-type features (seats) that have no reset window." + } + }, + "required": [ + "feature", + "enabled", + "type", + "quota", + "used", + "resetsAt" + ] + }, + "EntitlementsPlanStatus": { + "type": "string", + "enum": [ + "active", + "trialing" + ], + "description": "Status of the subscription the plan comes from" + }, + "EntitlementsPlan": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Plan identifier in the billing service" }, - "messagesTag": { + "name": { "type": "string", "nullable": true + }, + "cycleEndsAt": { + "format": "date-time", + "type": "string", + "nullable": true, + "description": "End of the current billing cycle" + }, + "status": { + "description": "Status of the subscription the plan comes from", + "allOf": [ + { + "$ref": "#/components/schemas/EntitlementsPlanStatus" + } + ] } }, - "required": [ - "address", - "chainId", - "nonce", - "threshold", - "owners", - "implementation", - "implementationVersionState" + "required": [ + "id", + "name", + "cycleEndsAt", + "status" ] }, - "SafeNonces": { + "EntitlementsResponse": { "type": "object", "properties": { - "currentNonce": { - "type": "number" + "plan": { + "nullable": true, + "description": "Null when the workspace has no active subscription.", + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/EntitlementsPlan" + } + ] }, - "recommendedNonce": { - "type": "number" + "entitlements": { + "type": "array", + "description": "One entry per catalog feature. Which fields an entry carries is decided by `type`: a metered one always carries quota, usage and its reset window, and the others never do.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/BinaryEntitlement" + }, + { + "$ref": "#/components/schemas/ValueEntitlement" + }, + { + "$ref": "#/components/schemas/MeteredEntitlement" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "binary": "#/components/schemas/BinaryEntitlement", + "value": "#/components/schemas/ValueEntitlement", + "metered": "#/components/schemas/MeteredEntitlement" + } + } + } } }, "required": [ - "currentNonce", - "recommendedNonce" + "plan", + "entitlements" ] }, - "SafeOverview": { + "SpaceRelayDto": { "type": "object", "properties": { - "address": { - "$ref": "#/components/schemas/AddressInfo" - }, - "chainId": { + "version": { "type": "string" }, - "threshold": { - "type": "number" - }, - "owners": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AddressInfo" - } + "to": { + "type": "string" }, - "fiatTotal": { + "data": { "type": "string" }, - "queued": { - "type": "number" + "safeTxHash": { + "type": "string", + "description": "Safe transaction hash, forwarded to the relay provider for traceability. Not verified against the calldata on this route." }, - "awaitingConfirmation": { - "type": "number", - "nullable": true + "acceptUnverifiedSimulation": { + "type": "boolean", + "description": "Set to true to proceed with the relay when a previous attempt returned INDETERMINATE_SIMULATION. The user has acknowledged the simulation could not be completed and accepts the risk." } }, "required": [ - "address", - "chainId", - "threshold", - "owners", - "fiatTotal", - "queued" + "version", + "to", + "data" ] }, - "SingleRecipientAnalysisResultDto": { + "Relay": { "type": "object", "properties": { - "severity": { + "taskId": { + "type": "string" + } + }, + "required": [ + "taskId" + ] + }, + "GasPaymentOptionUnavailableResponse": { + "type": "object", + "properties": { + "code": { "type": "string", - "description": "Severity level indicating the importance and risk", "enum": [ - "OK", - "INFO", - "WARN", - "CRITICAL" + "GAS_PAYMENT_OPTION_UNAVAILABLE" ] }, - "type": { + "message": { "type": "string", - "description": "Recipient interaction status code", - "enum": [ - "NEW_RECIPIENT", - "RECURRING_RECIPIENT", - "LOW_ACTIVITY", - "FAILED" - ], - "example": "NEW_RECIPIENT" + "description": "Human-readable description of the error. Informational only; do not parse." }, - "title": { + "statusCode": { + "type": "number", + "example": 409 + }, + "requested": { "type": "string", - "description": "User-facing title of the finding" + "enum": [ + "FREE_DAILY_LIMIT", + "SUBSCRIPTION", + "PAY_FROM_SAFE", + "NO_FEE_CAMPAIGN" + ], + "description": "The gas payment option the request needed." }, - "description": { + "reason": { "type": "string", - "description": "Detailed description explaining the finding and its implications" + "enum": [ + "NOT_LISTED", + "NO_RELAYER", + "NOT_A_WORKSPACE_SAFE", + "REFUNDING_TRANSACTION" + ], + "description": "NOT_LISTED: the chain does not list the option. NO_RELAYER: the chain has no relayer. NOT_A_WORKSPACE_SAFE: the Safe is not one the workspace holds. REFUNDING_TRANSACTION: the transaction would refund gas (`gasPrice` > 0)." }, - "error": { + "available": { + "type": "array", + "description": "The options the chain lists; empty without a relayer.", + "items": { + "type": "string", + "enum": [ + "FREE_DAILY_LIMIT", + "SUBSCRIPTION", + "PAY_FROM_SAFE", + "NO_FEE_CAMPAIGN" + ] + } + } + }, + "required": [ + "code", + "message", + "statusCode", + "requested", + "reason", + "available" + ] + }, + "CreateSafenetCheckDto": { + "type": "object", + "properties": { + "safeTxHash": { "type": "string", - "description": "Error message for failed analysis" + "description": "Safe transaction hash" } }, "required": [ - "severity", - "type", - "title", - "description" + "safeTxHash" ] }, - "SingleRecipientAnalysisDto": { + "SafeList": { "type": "object", "properties": { - "RECIPIENT_INTERACTION": { - "description": "Analysis results related to recipient interaction history. Shows whether this is a new or recurring recipient.", - "example": [ - { - "severity": "INFO", - "type": "NEW_RECIPIENT", - "title": "New recipient", - "description": "This is the first time you are interacting with this recipient." - } - ], - "type": "array", - "items": { - "$ref": "#/components/schemas/SingleRecipientAnalysisResultDto" - } - }, - "RECIPIENT_ACTIVITY": { - "description": "Analysis results related to recipient activity. Shows whether this is a low activity recipient. (Available only for Safes)", - "example": [ - { - "severity": "WARN", - "type": "LOW_ACTIVITY", - "title": "Low activity recipient", - "description": "This address has few transactions." - } - ], + "safes": { "type": "array", "items": { - "$ref": "#/components/schemas/SingleRecipientAnalysisResultDto" + "type": "string" } - }, - "isSafe": { - "type": "boolean", - "description": "Indicates whether the analyzed recipient address is a Safe.", - "example": false } }, "required": [ - "RECIPIENT_INTERACTION", - "isSafe" + "safes" ] }, - "CounterpartyAnalysisRequestDto": { + "RelayDto": { "type": "object", "properties": { + "version": { + "type": "string" + }, "to": { - "type": "string", - "description": "Recipient address of the transaction." + "type": "string" }, - "value": { + "data": { + "type": "string" + }, + "gasLimit": { "type": "string", - "description": "Amount to send with the transaction." + "nullable": true, + "description": "Accepted for backward compatibility and validation; not forwarded to the relay provider." }, - "data": { + "safeTxHash": { "type": "string", - "description": "Hex-encoded data payload for the transaction." + "description": "Safe transaction hash for relay-fee eligibility check" }, - "operation": { - "type": "number", - "enum": [ - 0, - 1 - ], - "description": "Operation type: 0 for CALL, 1 for DELEGATECALL." + "acceptUnverifiedSimulation": { + "type": "boolean", + "description": "Set to true to proceed with the relay when a previous attempt returned INDETERMINATE_SIMULATION. The user has acknowledged the simulation could not be completed and accepts the risk." } }, "required": [ + "version", "to", - "value", - "data", - "operation" + "data" ] }, - "RecipientResultDto": { + "RelayErrorResponse": { "type": "object", "properties": { - "severity": { - "type": "string", - "description": "Severity level indicating the importance and risk", - "enum": [ - "OK", - "INFO", - "WARN", - "CRITICAL" - ] - }, - "type": { + "code": { "type": "string", - "description": "Bridge compatibility status code", "enum": [ - "NEW_RECIPIENT", - "RECURRING_RECIPIENT", - "LOW_ACTIVITY", - "INCOMPATIBLE_SAFE", - "MISSING_OWNERSHIP", - "UNSUPPORTED_NETWORK", - "DIFFERENT_SAFE_SETUP", - "FAILED" + "SIMULATION_FAILED", + "INDETERMINATE_SIMULATION" ], - "example": "MISSING_OWNERSHIP" - }, - "title": { - "type": "string", - "description": "User-facing title of the finding" - }, - "description": { - "type": "string", - "description": "Detailed description explaining the finding and its implications" + "description": "Stable identifier of the error condition. The frontend MUST branch on this value (not on `message`, which is informational and may change)." }, - "error": { + "message": { "type": "string", - "description": "Error message for failed analysis" + "description": "Human-readable description of the error. Informational only; do not parse." }, - "targetChainId": { + "statusCode": { + "type": "number", + "example": 422 + } + }, + "required": [ + "code", + "message", + "statusCode" + ] + }, + "RelayTaskStatusReceipt": { + "type": "object", + "properties": { + "transactionHash": { "type": "string", - "description": "Target chain ID for bridge operations. Only present for BridgeStatus." + "example": "0x4e4bb4493b2183061c3a0106ea96604edcc84f83313dbc0ab718abb1523d1042" } }, "required": [ - "severity", - "type", - "title", - "description" + "transactionHash" ] }, - "RecipientAnalysisDto": { + "RelayTaskStatus": { "type": "object", "properties": { - "isSafe": { - "type": "boolean", - "description": "Indicates whether the analyzed recipient address is a Safe.", - "example": true - }, - "RECIPIENT_INTERACTION": { - "description": "Analysis results related to recipient interaction history. Shows whether this is a new or recurring recipient.", - "example": [ - { - "severity": "INFO", - "type": "NEW_RECIPIENT", - "title": "New recipient", - "description": "This is the first time you are interacting with this recipient." - } - ], - "type": "array", - "items": { - "$ref": "#/components/schemas/RecipientResultDto" - } - }, - "RECIPIENT_ACTIVITY": { - "description": "Analysis results related to recipient activity frequency. Shows whether this is a low activity recipient.", - "example": [ - { - "severity": "WARN", - "type": "LOW_ACTIVITY", - "title": "Low activity recipient", - "description": "This address has few transactions." - } + "status": { + "type": "number", + "description": "Relay task status code: 100=Pending, 110=Submitted, 200=Included, 400=Rejected, 500=Reverted", + "enum": [ + 100, + 110, + 200, + 400, + 500 ], - "type": "array", - "items": { - "$ref": "#/components/schemas/RecipientResultDto" - } + "example": 200 }, - "BRIDGE": { - "description": "Analysis results for cross-chain bridge operations. Identifies compatibility issues, ownership problems, or unsupported networks.", - "example": [ + "receipt": { + "description": "On-chain receipt. Only present when status is 200 (Included) or 500 (Reverted)", + "allOf": [ { - "severity": "WARN", - "type": "MISSING_OWNERSHIP", - "title": "No ownership on target chain", - "description": "You do not have ownership of a Safe on the target chain.", - "targetChainId": "137" + "$ref": "#/components/schemas/RelayTaskStatusReceipt" } - ], - "type": "array", - "items": { - "$ref": "#/components/schemas/RecipientResultDto" - } + ] } }, "required": [ - "isSafe" + "status" ] }, - "ContractAnalysisResultDto": { + "RelaysRemaining": { "type": "object", "properties": { - "severity": { - "type": "string", - "description": "Severity level indicating the importance and risk", - "enum": [ - "OK", - "INFO", - "WARN", - "CRITICAL" - ] - }, - "type": { - "type": "string", - "description": "Contract verification status code", - "enum": [ - "VERIFIED", - "NOT_VERIFIED", - "NOT_VERIFIED_BY_SAFE", - "VERIFICATION_UNAVAILABLE", - "NEW_CONTRACT", - "KNOWN_CONTRACT", - "UNEXPECTED_DELEGATECALL", - "UNOFFICIAL_FALLBACK_HANDLER", - "FAILED" - ], - "example": "VERIFIED" - }, - "title": { - "type": "string", - "description": "User-facing title of the finding" - }, - "description": { - "type": "string", - "description": "Detailed description explaining the finding and its implications" + "remaining": { + "type": "number" }, - "error": { - "type": "string", - "description": "Error message for failed analysis" + "limit": { + "type": "number" } }, "required": [ - "severity", - "type", - "title", - "description" + "remaining", + "limit" ] }, - "FallbackHandlerInfoDto": { + "SafeAppProvider": { "type": "object", "properties": { - "address": { - "type": "string", - "description": "Address of the fallback handler contract" + "url": { + "type": "string" }, "name": { - "type": "string", - "description": "Name of the fallback handler contract" + "type": "string" + } + }, + "required": [ + "url", + "name" + ] + }, + "SafeAppAccessControl": { + "type": "object", + "properties": { + "type": { + "type": "string" }, - "logoUrl": { - "type": "string", - "description": "Logo URL for the fallback handler contract" + "value": { + "nullable": true, + "type": "array", + "items": { + "type": "string" + } } }, "required": [ - "address" + "type" ] }, - "FallbackHandlerAnalysisResultDto": { + "SafeAppSocialProfile": { "type": "object", "properties": { - "severity": { + "platform": { "type": "string", - "description": "Severity level indicating the importance and risk", "enum": [ - "OK", - "INFO", - "WARN", - "CRITICAL" + "DISCORD", + "GITHUB", + "TWITTER", + "TELEGRAM", + "UNKNOWN" ] }, - "type": { - "type": "string", - "description": "Status code for unofficial fallback handler", - "enum": [ - "UNOFFICIAL_FALLBACK_HANDLER" - ], - "example": "VERIFIED" + "url": { + "type": "string" + } + }, + "required": [ + "platform", + "url" + ] + }, + "SafeApp": { + "type": "object", + "properties": { + "id": { + "type": "number" }, - "title": { + "url": { + "type": "string" + }, + "name": { + "type": "string" + }, + "iconUrl": { "type": "string", - "description": "User-facing title of the finding" + "nullable": true }, "description": { - "type": "string", - "description": "Detailed description explaining the finding and its implications" + "type": "string" }, - "error": { - "type": "string", - "description": "Error message for failed analysis" + "chainIds": { + "type": "array", + "items": { + "type": "string" + } }, - "fallbackHandler": { - "description": "Information about the fallback handler", + "provider": { + "nullable": true, + "type": "object", "allOf": [ { - "$ref": "#/components/schemas/FallbackHandlerInfoDto" + "$ref": "#/components/schemas/SafeAppProvider" } ] + }, + "accessControl": { + "$ref": "#/components/schemas/SafeAppAccessControl" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + }, + "features": { + "type": "array", + "items": { + "type": "string" + } + }, + "developerWebsite": { + "type": "string", + "nullable": true + }, + "socialProfiles": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SafeAppSocialProfile" + } + }, + "featured": { + "type": "boolean" } }, "required": [ - "severity", - "type", - "title", - "description" + "id", + "url", + "name", + "description", + "chainIds", + "accessControl", + "tags", + "features", + "socialProfiles", + "featured" ] }, - "ContractAnalysisDto": { + "SafeState": { "type": "object", "properties": { - "logoUrl": { - "type": "string", - "description": "Logo URL for the contract", - "example": "https://example.com/logo.png" + "address": { + "$ref": "#/components/schemas/AddressInfo" }, - "name": { - "type": "string", - "description": "Name of the contract", - "example": "Uniswap V3 Router" + "chainId": { + "type": "string" }, - "CONTRACT_VERIFICATION": { - "description": "Analysis results for contract verification status. Shows whether contracts are verified and source code is available.", - "example": [ - { - "severity": "INFO", - "type": "VERIFIED", - "title": "Verified contract", - "description": "This contract has been verified and its source code is available" - } - ], + "nonce": { + "type": "number" + }, + "threshold": { + "type": "number" + }, + "owners": { "type": "array", "items": { - "$ref": "#/components/schemas/ContractAnalysisResultDto" + "$ref": "#/components/schemas/AddressInfo" } }, - "CONTRACT_INTERACTION": { - "description": "Analysis results related to contract interaction history. Shows whether this is a new or previously interacted contract.", - "example": [ - { - "severity": "INFO", - "type": "NEW_CONTRACT", - "title": "New contract", - "description": "This is the first time you are interacting with this contract" - } - ], + "implementation": { + "$ref": "#/components/schemas/AddressInfo" + }, + "modules": { + "nullable": true, "type": "array", "items": { - "$ref": "#/components/schemas/ContractAnalysisResultDto" + "$ref": "#/components/schemas/AddressInfo" } }, - "DELEGATECALL": { - "description": "Analysis results for delegatecall operations. Identifies unexpected or potentially dangerous delegate calls.", - "example": [ + "fallbackHandler": { + "nullable": true, + "type": "object", + "allOf": [ { - "severity": "CRITICAL", - "type": "UNEXPECTED_DELEGATECALL", - "title": "Unexpected delegatecall", - "description": "An unexpected delegatecall operation was detected that could be dangerous" + "$ref": "#/components/schemas/AddressInfo" } - ], - "type": "array", - "items": { - "$ref": "#/components/schemas/ContractAnalysisResultDto" - } + ] }, - "FALLBACK_HANDLER": { - "description": "Analysis results for setFallbackHandler operations. Identifies untrusted or unofficial fallback handlers in the transactions.", - "example": [ + "guard": { + "nullable": true, + "type": "object", + "allOf": [ { - "severity": "WARN", - "type": "UNOFFICIAL_FALLBACK_HANDLER", - "title": "Unofficial fallback handler", - "description": "Verify the fallback handler is trusted and secure before proceeding.", - "fallbackHandler": { - "address": "0x123", - "name": "CompatibilityFallbackHandler", - "logoUrl": "https://example.com/logo.png" - } + "$ref": "#/components/schemas/AddressInfo" } - ], - "type": "array", - "items": { - "$ref": "#/components/schemas/FallbackHandlerAnalysisResultDto" - } - } - } - }, - "DeadlockAnalysisResultDto": { - "type": "object", - "properties": { - "severity": { + ] + }, + "version": { + "type": "string", + "nullable": true + }, + "implementationVersionState": { "type": "string", - "description": "Severity level indicating the importance and risk", "enum": [ - "OK", - "INFO", - "WARN", - "CRITICAL" + "UP_TO_DATE", + "OUTDATED", + "UNKNOWN" ] }, - "type": { + "collectiblesTag": { "type": "string", - "description": "Deadlock analysis status code", - "enum": [ - "DEADLOCK_DETECTED", - "NESTED_SAFE_WARNING", - "FAILED" - ], - "example": "DEADLOCK_DETECTED" + "nullable": true }, - "title": { + "txQueuedTag": { "type": "string", - "description": "User-facing title of the finding" + "nullable": true }, - "description": { + "txHistoryTag": { "type": "string", - "description": "Detailed description explaining the finding and its implications" + "nullable": true }, - "error": { + "messagesTag": { "type": "string", - "description": "Error message for failed analysis" + "nullable": true } }, "required": [ - "severity", - "type", - "title", - "description" + "address", + "chainId", + "nonce", + "threshold", + "owners", + "implementation", + "implementationVersionState" ] }, - "DeadlockAnalysisDto": { + "SafeNonces": { "type": "object", "properties": { - "DEADLOCK": { - "description": "Deadlock analysis findings. Identifies signing deadlock risks in nested Safe configurations.", - "example": [ - { - "severity": "CRITICAL", - "type": "DEADLOCK_DETECTED", - "title": "Signing deadlock risk detected", - "description": "This change may create a signing cycle between Safes and can permanently lock funds. You will not be allowed to proceed forward." - } - ], - "type": "array", - "items": { - "$ref": "#/components/schemas/DeadlockAnalysisResultDto" - } + "currentNonce": { + "type": "number" + }, + "recommendedNonce": { + "type": "number" } - } + }, + "required": [ + "currentNonce", + "recommendedNonce" + ] }, - "CounterpartyAnalysisDto": { + "SafeOverview": { "type": "object", "properties": { - "recipient": { - "type": "object", - "description": "Recipient analysis results mapped by address. Contains recipient interaction history and bridge analysis.type: Record.", - "additionalProperties": { - "$ref": "#/components/schemas/RecipientAnalysisDto" - }, - "example": { - "0x0000000000000000000000000000000000000000": { - "isSafe": true, - "RECIPIENT_INTERACTION": [ - { - "severity": "INFO", - "type": "NEW_RECIPIENT", - "title": "New recipient", - "description": "This is the first time you are interacting with this recipient" - } - ] - } - } + "address": { + "$ref": "#/components/schemas/AddressInfo" }, - "contract": { - "type": "object", - "description": "Contract analysis results mapped by address. Contains contract verification, interaction history, and delegatecall analysis.type: Record.", - "additionalProperties": { - "$ref": "#/components/schemas/ContractAnalysisDto" - }, - "example": { - "0x0000000000000000000000000000000000000000": { - "CONTRACT_VERIFICATION": [ - { - "severity": "INFO", - "type": "VERIFIED", - "title": "Verified contract", - "description": "This contract has been verified and its source code is available" - } - ] - } - } + "chainId": { + "type": "string" }, - "deadlock": { - "type": "object", - "description": "Deadlock analysis results mapped by Safe address. Contains signing deadlock risk findings for owner/threshold management transactions.", - "additionalProperties": { - "$ref": "#/components/schemas/DeadlockAnalysisDto" - }, - "example": { - "0x0000000000000000000000000000000000000000": { - "DEADLOCK": [ - { - "severity": "CRITICAL", - "type": "DEADLOCK_DETECTED", - "title": "Signing deadlock risk detected", - "description": "This change may create a signing cycle between Safes and can permanently lock funds. You will not be allowed to proceed forward." - } - ] - } + "threshold": { + "type": "number" + }, + "owners": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AddressInfo" } + }, + "fiatTotal": { + "type": "string" + }, + "queued": { + "type": "number" + }, + "awaitingConfirmation": { + "type": "number", + "nullable": true } }, "required": [ - "recipient", - "contract", - "deadlock" + "address", + "chainId", + "threshold", + "owners", + "fiatTotal", + "queued" ] }, "ThreatAnalysisRequestDto": { @@ -14277,6 +17348,7 @@ } }, "rejectors": { + "deprecated": true, "type": "array", "items": { "$ref": "#/components/schemas/AddressInfo" @@ -14355,25 +17427,6 @@ "address" ] }, - "SafeAppInfo": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "url": { - "type": "string" - }, - "logoUri": { - "type": "string", - "nullable": true - } - }, - "required": [ - "name", - "url" - ] - }, "TransactionDetails": { "type": "object", "properties": { @@ -15084,6 +18137,64 @@ "results" ] }, + "NestedTransactionDto": { + "type": "object", + "properties": { + "to": { + "type": "string", + "nullable": true + }, + "value": { + "type": "string" + }, + "data": { + "type": "string", + "nullable": true + }, + "operation": { + "description": "Operation type: 0 for CALL, 1 for DELEGATE", + "allOf": [ + { + "$ref": "#/components/schemas/Operation" + } + ] + }, + "safeTxGas": { + "type": "string" + }, + "baseGas": { + "type": "string" + }, + "gasPrice": { + "type": "string" + }, + "gasToken": { + "type": "string", + "nullable": true + }, + "refundReceiver": { + "type": "string", + "nullable": true + }, + "nonce": { + "type": "string", + "description": "The nested Safe's nonce" + }, + "notes": { + "type": "string", + "nullable": true, + "maxLength": 200 + } + }, + "required": [ + "value", + "operation", + "safeTxGas", + "baseGas", + "gasPrice", + "nonce" + ] + }, "ProposeTransactionDto": { "type": "object", "properties": { @@ -15137,6 +18248,16 @@ "origin": { "type": "string", "nullable": true + }, + "nestedTransaction": { + "nullable": true, + "description": "A child transaction for a second Safe, authorised by the parent transaction being an `approveHash` call committing to its hash. Unknown keys are rejected.", + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/NestedTransactionDto" + } + ] } }, "required": [ @@ -15435,6 +18556,169 @@ "signature" ] }, + "UpdateDelegateV3Dto": { + "type": "object", + "properties": { + "safe": { + "type": "string", + "nullable": true + }, + "delegate": { + "type": "string" + }, + "delegator": { + "type": "string" + }, + "signature": { + "type": "string" + }, + "label": { + "type": "string" + } + }, + "required": [ + "delegate", + "delegator", + "signature", + "label" + ] + }, + "DeleteDelegateV3Dto": { + "type": "object", + "properties": { + "delegator": { + "type": "string", + "nullable": true + }, + "safe": { + "type": "string", + "nullable": true + }, + "signature": { + "type": "string" + } + }, + "required": [ + "signature" + ] + }, + "NativeTokenMetadata": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "decimals": { + "type": "number" + }, + "logoUri": { + "type": "string" + }, + "name": { + "type": "string" + }, + "symbol": { + "type": "string" + }, + "trusted": { + "type": "boolean", + "description": "Whether the Transaction Service lists the token in one of its imported token lists" + }, + "type": { + "type": "string", + "enum": [ + "NATIVE_TOKEN" + ] + } + }, + "required": [ + "address", + "decimals", + "logoUri", + "name", + "symbol", + "trusted", + "type" + ] + }, + "Erc20TokenMetadata": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "decimals": { + "type": "number" + }, + "logoUri": { + "type": "string" + }, + "name": { + "type": "string" + }, + "symbol": { + "type": "string" + }, + "trusted": { + "type": "boolean", + "description": "Whether the Transaction Service lists the token in one of its imported token lists" + }, + "type": { + "type": "string", + "enum": [ + "ERC20" + ] + } + }, + "required": [ + "address", + "decimals", + "logoUri", + "name", + "symbol", + "trusted", + "type" + ] + }, + "Erc721TokenMetadata": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "decimals": { + "type": "number" + }, + "logoUri": { + "type": "string" + }, + "name": { + "type": "string" + }, + "symbol": { + "type": "string" + }, + "trusted": { + "type": "boolean", + "description": "Whether the Transaction Service lists the token in one of its imported token lists" + }, + "type": { + "type": "string", + "enum": [ + "ERC721" + ] + } + }, + "required": [ + "address", + "decimals", + "logoUri", + "name", + "symbol", + "trusted", + "type" + ] + }, "SafeRegistration": { "type": "object", "properties": { diff --git a/packages/store/src/gateway/AUTO_GENERATED/.schema-hash b/packages/store/src/gateway/AUTO_GENERATED/.schema-hash index 3de9ddc2277..f87f6f01319 100644 --- a/packages/store/src/gateway/AUTO_GENERATED/.schema-hash +++ b/packages/store/src/gateway/AUTO_GENERATED/.schema-hash @@ -1 +1 @@ -e9984df7d8acc32efa5370bd62918903c1a9aedda334828d00ef55ff0e922556 +015c768c74175ce15472b5952479837324ef422f0683b0cac5682a4c5d8c07f7 diff --git a/packages/store/src/gateway/AUTO_GENERATED/chains.ts b/packages/store/src/gateway/AUTO_GENERATED/chains.ts index c072860f9cf..a46c104237e 100644 --- a/packages/store/src/gateway/AUTO_GENERATED/chains.ts +++ b/packages/store/src/gateway/AUTO_GENERATED/chains.ts @@ -154,8 +154,11 @@ export type Theme = { export type Relayer = { type: ('GTF' | 'RELAY_FEE' | 'DAILY_LIMIT' | 'NO_FEE_CAMPAIGN') | null safeCreationSponsored: boolean + /** Use gasPaymentOptions instead. */ safeTransactionSponsored: boolean enableTenderlySimulationBeforeRelay: boolean + /** Who may pay for a relayed transaction on this chain. */ + gasPaymentOptions: ('FREE_DAILY_LIMIT' | 'SUBSCRIPTION' | 'PAY_FROM_SAFE' | 'NO_FEE_CAMPAIGN')[] } export type Chain = { chainId: string diff --git a/packages/store/src/gateway/AUTO_GENERATED/delegates.ts b/packages/store/src/gateway/AUTO_GENERATED/delegates.ts index 1cee45c5104..4f7910b2ef1 100644 --- a/packages/store/src/gateway/AUTO_GENERATED/delegates.ts +++ b/packages/store/src/gateway/AUTO_GENERATED/delegates.ts @@ -64,6 +64,43 @@ const injectedRtkApi = api }), invalidatesTags: ['delegates'], }), + delegatesGetDelegatesV3: build.query