{"components":{"securitySchemes":{"ApiKeyAuth":{"description":"For accessing these endpoints a valid API key must be sent in the *X-Api-Key* header.\n","in":"header","name":"X-Api-Key","type":"apiKey"},"BasicAuth":{"description":"Access control to the API is always controlled by a JWT token. To get this token you must log in through */v3/signin* (email and password).\n\nThe client sends requests with the Authorization header that contains the Basic word followed by a space and a base64-encoded username:password string.\nExample:\n    Authorization: Basic ZGVtbzpwQDU1dzByZA==\n","in":"header","name":"Authorization","type":"apiKey"},"CustomApiKey":{"description":"For accessing a specific API endpoint of this type, a valid API key must be passed in the *Authorization* header.\n","in":"header","name":"Authorization","type":"apiKey"},"JwtAuth":{"description":"For accessing the API a valid JWT token must be passed in the *Authorization* header.\n\nA valid JWT token is generated by the API and returned after calling */v1/signin* with valid credentials.\n\nExample:\n    Authorization: Bearer xxxxxx.yyyyyyy.zzzzzz\n","in":"header","name":"Authorization","type":"apiKey"}}},"info":{"title":"Bit2Me API Gateway","version":"2.0.0"},"openapi":"3.0.4","paths":{"/v1/account":{"delete":{"description":"Deletes the authenticated user's account. This action is irreversible and removes all\naccount data, wallets and associated information.\n\nThe gateway injects the authenticated user's identity; the caller does not send it.\n","responses":{"200":{"content":{"application/json":{"example":{"result":true},"schema":{"properties":{"result":{"type":"boolean"}},"required":["result"],"type":"object"}}},"description":"Account deleted."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Delete account","tags":["Account"],"x-product":{"wallet":"Account"}}},"/v1/account/address":{"delete":{"description":"Removes an address from the authenticated user. The `addressId` query parameter\nidentifies which address to delete.\n","parameters":[{"description":"UUID of the address to delete.","in":"query","name":"addressId","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"204":{"content":{"application/json":{"schema":{"properties":{"result":{"type":"boolean"}},"required":["result"],"type":"object"}}},"description":"Address deleted."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Delete address","tags":["Account"],"x-product":{"wallet":"Account"}},"put":{"description":"Updates an existing address for the authenticated user. The `addressId` query parameter\nidentifies which address to modify.\n","parameters":[{"description":"UUID of the address to update.","in":"query","name":"addressId","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"city":"Barcelona","countryCode":"ES","stateCode":"CT","streetAddress":"Calle Nueva 42","zip":"08001"},"schema":{"properties":{"alias":{"maxLength":50,"type":"string"},"city":{"type":"string"},"countryCode":{"pattern":"^[A-Z]{2}$","type":"string"},"id":{"type":"string"},"isDefaultAddress":{"type":"boolean"},"isResidence":{"type":"boolean"},"stateCode":{"type":"string"},"streetAddress":{"type":"string"},"userId":{"type":"string"},"zip":{"type":"string"}},"required":["streetAddress","city","stateCode","zip","countryCode"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"items":{"properties":{"alias":{"maxLength":50,"type":"string"},"city":{"type":"string"},"countryCode":{"pattern":"^[A-Z]{2}$","type":"string"},"id":{"type":"string"},"isDefaultAddress":{"type":"boolean"},"isResidence":{"type":"boolean"},"stateCode":{"type":"string"},"streetAddress":{"type":"string"},"userId":{"type":"string"},"zip":{"type":"string"}},"required":["streetAddress","city","stateCode","zip","countryCode"],"type":"object"},"type":"array"}}},"description":"Updated address list."},"400":{"content":{"application/json":{"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"Incorrect address fields."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"User or address not found."},"406":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Residence already established."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Update address","tags":["Account"],"x-product":{"wallet":"Account"}}},"/v1/account/deposit-estimation":{"get":{"description":"Returns the list of available deposit estimation ranges. Each range represents a bracket\n(minimum–maximum) the user can select during onboarding.\n","responses":{"200":{"content":{"application/json":{"example":{"data":[{"id":"1","maximum":1000,"minimum":0},{"id":"2","maximum":10000,"minimum":1000},{"id":"3","maximum":100000,"minimum":10000}],"total":3},"schema":{"properties":{"data":{"items":{"properties":{"id":{"type":"string"},"maximum":{"type":"number"},"minimum":{"type":"number"}},"type":"object"},"type":"array"},"total":{"type":"number"}},"required":["total","data"],"type":"object"}}},"description":"Available deposit estimation ranges."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get deposit estimations","tags":["Account"],"x-product":{"wallet":"Account"}}},"/v1/account/employment-status":{"get":{"deprecated":true,"description":"**This endpoint is deprecated.** Use `GET /v2/account/employment-status` instead, which\nreturns translation keys instead of pre-translated text.\n","parameters":[{"description":"ISO 639-1 language code for translations (e.g. `es`, `en`).","in":"query","name":"langCode","required":true,"schema":{"pattern":"^[a-z]{2}$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"properties":{"description":{"type":"string"},"id":{"type":"string"},"langCode":{"type":"string"},"name":{"type":"string"}},"type":"object"},"type":"array"},"total":{"type":"number"}},"required":["total","data"],"type":"object"}}},"description":"List of employment status options."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Deprecated, use GET /v2/account/employment-status instead","tags":["Account Deprecated Methods"],"x-product":{"wallet":"Account"},"x-use":"GET /v2/account/employment-status"}},"/v1/account/funds-origin":{"get":{"deprecated":true,"description":"**This endpoint is deprecated.** Use `GET /v2/account/funds-origin` instead, which returns\ntranslation keys instead of pre-translated text.\n","parameters":[{"description":"ISO 639-1 language code for translations (e.g. `es`, `en`).","in":"query","name":"langCode","schema":{"pattern":"^[a-z]{2}$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"properties":{"description":{"type":"string"},"id":{"type":"string"},"langCode":{"type":"string"},"name":{"type":"string"}},"type":"object"},"type":"array"},"total":{"type":"number"}},"required":["total","data"],"type":"object"}}},"description":"List of fund origin options."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Deprecated, use GET /v2/account/funds-origin instead","tags":["Account Deprecated Methods"],"x-product":{"wallet":"Account"},"x-use":"GET /v2/account/funds-origin"}},"/v1/account/professions":{"get":{"deprecated":true,"description":"**This endpoint is deprecated.** Use `GET /v2/account/professions` instead, which returns\ntranslation keys instead of pre-translated text.\n","parameters":[{"description":"ISO 639-1 language code for translations (e.g. `es`, `en`).","in":"query","name":"langCode","schema":{"pattern":"^[a-z]{2}$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"properties":{"description":{"type":"string"},"id":{"type":"string"},"langCode":{"type":"string"},"professionCode":{"type":"string"}},"required":["id","description","professionCode","langCode"],"type":"object"},"type":"array"},"total":{"type":"integer"}},"required":["total","data"],"type":"object"}}},"description":"List of professions."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Deprecated, use GET /v2/account/professions instead","tags":["Account Deprecated Methods"],"x-product":{"wallet":"Account"},"x-use":"GET /v2/account/professions"}},"/v1/account/purposes":{"get":{"deprecated":true,"description":"**This endpoint is deprecated.** Use `GET /v2/account/purposes` instead, which returns\ntranslation keys instead of pre-translated text.\n","parameters":[{"description":"ISO 639-1 language code for translations (e.g. `es`, `en`).","in":"query","name":"langCode","schema":{"pattern":"^[a-z]{2}$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"properties":{"description":{"type":"string"},"id":{"type":"string"},"langCode":{"type":"string"},"name":{"type":"string"}},"required":["id","name","description","langCode"],"type":"object"},"type":"array"},"total":{"type":"integer"}},"required":["total","data"],"type":"object"}}},"description":"List of account purposes."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Deprecated, use GET /v2/account/purposes instead","tags":["Account Deprecated Methods"],"x-product":{"wallet":"Account"},"x-use":"GET /v2/account/purposes"}},"/v1/account/settings/sfa":{"post":{"description":"Starts the process to enable Google Authenticator (TOTP) two-factor authentication.\nReturns a QR image, a shared secret, and a display name for the authenticator app.\n\nAfter calling this endpoint the caller must present the QR to the user and then call\n`PUT /v1/account/settings/sfa` with the six-digit code to complete enablement.\n\nIf the user already has 2FA enabled the service returns `409`. If a previous SFA\nchallenge is active the service may return `428` with SFA metadata.\n","responses":{"200":{"content":{"application/json":{"example":{"name":"Bit2Me (john@example.com)","qrImage":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...","secret":"JBSWY3DPEHPK3PXP"},"schema":{"properties":{"name":{"description":"Display name for the authenticator app entry.","type":"string"},"qrImage":{"description":"Data URI containing a PNG QR code (e.g. `data:image/png;base64,iVB…`).","type":"string"},"secret":{"description":"Base-32 encoded shared secret key.","type":"string"}},"required":["qrImage","secret","name"],"type":"object"}}},"description":"TOTP setup initiated — QR and secret returned."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"User not found."},"409":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Second-factor authentication already enabled."},"420":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Two-factor authentication code not valid (when retrying after a failed attempt)."},"428":{"content":{"application/json":{"example":{"data":{"availableChannels":["sms","whatsapp"],"defaultChannel":"sms","retryIntervalSeconds":60,"sfaProcessInitialized":true,"sfaType":"sms"},"error":"Precondition Required","message":"sfa required","statusCode":428},"schema":{"allOf":[{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"},{"properties":{"data":{"allOf":[{"properties":{"availableChannels":{"description":"Phone OTP channels available for the current user","items":{"enum":["sms","call","whatsapp"],"type":"string"},"type":"array"},"defaultChannel":{"enum":["sms","call","whatsapp"],"type":"string"}},"type":"object"},{"properties":{"retryIntervalSeconds":{"type":"integer"},"sfaProcessInitialized":{"type":"boolean"},"sfaType":{"enum":["gauth","sms","email","call","whatsapp"],"type":"string"}},"type":"object"}]}},"type":"object"}]}}},"description":"Two-factor authentication required before this operation can proceed.\nThe response includes SFA metadata inside `data`.\n"},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Start two-factor authentication setup","tags":["Auth"],"x-product":{"wallet":"Account"}},"put":{"description":"Completes the TOTP enablement started by `POST /v1/account/settings/sfa`.\nThe caller provides the six-digit TOTP code from the authenticator app to verify that\nthe server-side and client-side secrets match.\n\nOptionally pass `alwaysRequired: true` to enforce 2FA on every login.\n","requestBody":{"content":{"application/json":{"example":{"alwaysRequired":true,"totp":"123456"},"schema":{"properties":{"alwaysRequired":{"description":"Whether two-factor authentication should always be required on login.","type":"boolean"},"sessionId":{"description":"Optional session identifier.","format":"uuid","type":"string"},"totp":{"description":"The six-digit TOTP code from the authenticator app.","pattern":"^[0-9]{6}$","type":"string"}},"required":["totp"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"result":true},"schema":{"properties":{"result":{"type":"boolean"}},"required":["result"],"type":"object"}}},"description":"Two-factor authentication enabled."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"User not found."},"409":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"TOTP code does not match — the server-side and client-side codes differ."},"412":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"The SFA setup process has not been initiated (call POST first)."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Complete two-factor authentication setup","tags":["Auth"],"x-product":{"wallet":"Account"}}},"/v1/account/subaccount":{"get":{"description":"Returns the list of subaccounts linked to the authenticated main account, optionally\nfiltered by subaccount type.\n","parameters":[{"description":"Filter by subaccount type (e.g. `junior`).","in":"query","name":"subaccountType","schema":{"enum":["junior"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"data":[{"email":"junior@example.com","id":"550e8400-e29b-41d4-a716-446655440099","name":"Alex","phone":{"countryCode":"34","number":"612345678"},"subaccountType":"junior","surname":"Smith","type":"person"}],"total":1},"schema":{"properties":{"data":{"items":{"properties":{"alias":{"type":"string"},"email":{"format":"email","maxLength":96,"minLength":6,"type":"string"},"id":{"pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"},"name":{"type":"string"},"phone":{"properties":{"countryCode":{"pattern":"^[0-9]{1,4}$","type":"string"},"number":{"maxLength":32,"pattern":"^[0-9]+$","type":"string"}},"required":["number","countryCode"],"type":"object"},"subaccountType":{"enum":["junior"],"type":"string"},"surname":{"type":"string"},"type":{"enum":["person","company","employee"],"type":"string"}},"type":"object"},"type":"array"},"total":{"description":"Total number of subaccounts matching the filter.","type":"number"}},"type":"object"}}},"description":"List of subaccounts."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"List subaccounts","tags":["Account"],"x-product":{"wallet":"Account"}},"post":{"description":"Creates a subaccount linked to the authenticated main account. The subaccount receives\nits own `userId` and can operate independently within the scope granted by the main\naccount.\n","requestBody":{"content":{"application/json":{"example":{"email":"junior@example.com","name":"Alex","phone":{"countryCode":"34","number":"612345678"},"surname":"Smith","type":"person"},"schema":{"properties":{"email":{"format":"email","maxLength":96,"minLength":6,"type":"string"},"name":{"description":"First name of the subaccount holder.","type":"string"},"phone":{"properties":{"countryCode":{"pattern":"^[0-9]{1,4}$","type":"string"},"number":{"maxLength":32,"pattern":"^[0-9]+$","type":"string"}},"required":["number","countryCode"],"type":"object"},"surname":{"description":"Last name of the subaccount holder.","type":"string"},"type":{"enum":["person","company","employee"],"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"userId":"550e8400-e29b-41d4-a716-446655440099"},"schema":{"properties":{"userId":{"pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}},"required":["userId"],"type":"object"}}},"description":"Subaccount created."},"400":{"content":{"application/json":{"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"Invalid email or phone format."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"409":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Email or phone already registered."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Create subaccount","tags":["Account"],"x-product":{"embed":"Auth flow","wallet":"Account"}}},"/v1/account/subaccount/sfa":{"post":{"description":"Starts the process to enable two-factor authentication for a subaccount.\nReturns the TOTP secret and QR code for the subaccount holder to configure their\nauthenticator app.\n","requestBody":{"content":{"application/json":{"example":{"subaccountUserId":"550e8400-e29b-41d4-a716-446655440002"},"schema":{"properties":{"subaccountUserId":{"description":"The subaccount user identifier.","format":"uuid","type":"string"}},"required":["subaccountUserId"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"algorithm":"SHA1","digits":6,"period":30,"qrCode":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...","secret":"JBSWY3DPEHPK3PXP"},"schema":{"properties":{"algorithm":{"description":"TOTP algorithm.","type":"string"},"digits":{"description":"Number of digits in the TOTP code.","type":"integer"},"period":{"description":"Time period in seconds for TOTP rotation.","type":"integer"},"qrCode":{"description":"Data URI containing a PNG QR code (e.g. `data:image/png;base64,iVB…`).","type":"string"},"secret":{"description":"Base-32 encoded TOTP secret key.","type":"string"}},"required":["secret","qrCode"],"type":"object"}}},"description":"TOTP setup initiated — secret and QR returned."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Subaccount not found."},"409":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"2FA already enabled for this subaccount."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Start subaccount 2FA setup","tags":["Auth"],"x-product":{"wallet":"Account"}},"put":{"description":"Completes the process to enable two-factor authentication for a subaccount.\nVerifies that the TOTP on the server side and the TOTP on the client side match.\n","requestBody":{"content":{"application/json":{"example":{"subaccountUserId":"550e8400-e29b-41d4-a716-446655440002","totp":"123456"},"schema":{"properties":{"subaccountUserId":{"description":"The subaccount user identifier.","format":"uuid","type":"string"},"totp":{"description":"The six-digit TOTP code from the authenticator app.","pattern":"^[0-9]{6}$","type":"string"}},"required":["subaccountUserId","totp"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"result":true},"schema":{"properties":{"result":{"type":"boolean"}},"required":["result"],"type":"object"}}},"description":"2FA enabled for subaccount."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Subaccount not found."},"409":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"TOTP code does not match."},"412":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"2FA setup process not initiated — call POST first."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Complete subaccount 2FA setup","tags":["Auth"],"x-product":{"wallet":"Account"}}},"/v1/account/update":{"put":{"description":"Updates account information for the authenticated user. Accepts partial updates — only\nthe fields present in the request body are modified.\n\nFields protected by the current verification level or that already have a value cannot\nbe overwritten; those attempts return `412`.\n\nThis route uses `WrapResponseDataOnStatus4xx`: business errors from the backing service\narrive wrapped inside `data` when the status is 4xx.\n\nThe gateway injects the authenticated user's identity; the caller does not send it.\n","requestBody":{"content":{"application/json":{"examples":{"update-alias":{"summary":"Set the account alias","value":{"alias":"my-new-alias"}},"update-profile":{"summary":"Change language and currency","value":{"profile":{"currencyCode":"EUR","langCode":"es","timeZone":"Europe/Madrid"}}}},"schema":{"properties":{"accountCompleted":{"description":"Mark the onboarding as finished.","type":"boolean"},"accountPurpose":{"enum":["savings","currencyExchange","investment","trading","cryptocurrencyPayments"],"type":"string"},"alias":{"pattern":"^[0-9a-z\\-_]{2,30}$","type":"string"},"company":{"properties":{"annualTradeEstimatedValue":{"type":"integer"},"attorneyInFact":{"properties":{"name":{"type":"string"},"numberOfDocument":{"maxLength":24,"type":"string"},"surname":{"type":"string"},"typeOfDocument":{"enum":["none","idcard","foreign-id-card","passport","drivinglicense","visa"],"type":"string"}},"type":"object"},"autonomus":{"type":"boolean"},"billingVolume":{"type":"integer"},"businessName":{"type":"string"},"constitutionCountryCode":{"pattern":"^[A-Z]{2}$","type":"string"},"constitutionDate":{"format":"date","type":"string"},"contact":{"properties":{"isPartner":{"type":"boolean"},"name":{"type":"string"},"numberOfDocument":{"maxLength":24,"type":"string"},"surname":{"type":"string"},"typeOfDocument":{"enum":["none","idcard","foreign-id-card","passport","drivinglicense","visa"],"type":"string"}},"type":"object"},"economicCapacityModel":{"enum":["model_200","model_390","model_303"],"type":"string"},"firstTradeEstimatedValue":{"type":"integer"},"identity":{"properties":{"countryCode":{"pattern":"^[A-Z]{2}$","type":"string"},"number":{"maxLength":24,"type":"string"},"type":{"enum":["none","idcard","passport","drivinglicense","visa","cif"],"type":"string"},"updatedAt":{"format":"date","type":"string"}},"type":"object"},"isSinglePartner":{"type":"boolean"},"kindOfSociety":{"type":"string"},"legalEntityId":{"maxLength":20,"type":"string"},"legalTerms":{"type":"boolean"},"numberOfPartners":{"type":"integer"},"obligedSubject":{"type":"boolean"},"otherServices":{"nullable":true,"type":"string"},"overTheCounter":{"type":"boolean"},"partners":{"items":{"properties":{"birthdate":{"format":"date","type":"string"},"deletedAt":{"format":"date","type":"string"},"documentCountryCode":{"pattern":"^[A-Z]{2}$","type":"string"},"documentExpirationDate":{"format":"date","type":"string"},"documentNumber":{"maxLength":24,"type":"string"},"documentType":{"enum":["none","idcard","foreign-id-card","passport","drivinglicense","visa"],"type":"string"},"isPoliticallyExposed":{"type":"boolean"},"name":{"type":"string"},"nationalityCountryCode":{"pattern":"^[A-Z]{2}$","type":"string"},"partnerId":{"pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"},"position":{"type":"string"},"sharePercentage":{"type":"number"},"surname":{"type":"string"}},"required":["partnerId"],"type":"object"},"type":"array"},"politicalPartners":{"items":{"properties":{"name":{"type":"string"},"position":{"type":"string"}},"required":["name","position"],"type":"object"},"type":"array"},"politicallyExposedPersonPartners":{"type":"boolean"},"reasonForTheOperation":{"items":{"type":"string"},"type":"array"},"registeredOffice":{"type":"string"},"sector":{"type":"string"},"service":{"type":"string"},"services":{"items":{"enum":["crypto_investment","send_crypto","liquidity","earn_loan","api","consulting","others"],"type":"string"},"type":"array"},"shareholdingStructure":{"nullable":true,"type":"string"},"taxId":{"maxLength":11,"type":"string"},"typeOfOperationsToPerform":{"items":{"type":"string"},"type":"array"},"webUrl":{"nullable":true,"type":"string"}},"type":"object"},"depositEstimation":{"properties":{"maximum":{"type":"integer"},"minimum":{"type":"integer"}},"required":["minimum","maximum"],"type":"object"},"fundsOrigin":{"properties":{"othersReason":{"type":"string"},"type":{"enum":["salary","incomes","pensions","propertiesSell","donations","investments","cryptoMining","others"],"type":"string"}},"required":["type"],"type":"object"},"person":{"properties":{"birthDate":{"format":"date","type":"string"},"employmentStatus":{"enum":["employed","selfEmployed","businessOwner","unemployed","student","others","retired"],"type":"string"},"gender":{"enum":["male","female","N/D"],"type":"string"},"identity":{"properties":{"countryCode":{"pattern":"^[A-Z]{2}$","type":"string"},"expiryDate":{"format":"date","type":"string"},"number":{"maxLength":24,"type":"string"},"type":{"enum":["idcard","foreign-id-card","passport","drivinglicense","visa"],"type":"string"}},"type":"object"},"name":{"maxLength":64,"type":"string"},"nationalityCountryCode":{"pattern":"^[A-Z]{2}$","type":"string"},"politicallyExposedPerson":{"type":"string"},"profession":{"type":"string"},"surname":{"maxLength":128,"type":"string"}},"type":"object"},"profile":{"description":"User preference settings.","properties":{"currencyCode":{"pattern":"^[A-Z]{3}$","type":"string"},"langCode":{"pattern":"^[a-z]{2}(-[A-Z]{2})?$","type":"string"},"timeZone":{"format":"^[A-Za-z_\\-\\\\]+$","maxLength":50,"type":"string"}},"type":"object"},"secondFactorAuth":{"properties":{"alwaysRequired":{"type":"boolean"}},"type":"object"},"selfInvoiceIdentityNumber":{"maxLength":30,"type":"string"},"so":{"description":"Operating system of the client.","type":"string"},"type":{"enum":["person","company","employee"],"type":"string"},"version":{"description":"Application version of the client.","type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"result":true},"schema":{"properties":{"result":{"type":"boolean"}},"required":["result"],"type":"object"}}},"description":"Account updated."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"409":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Duplicated key (TIN, ID card number, passport number, etc.)."},"412":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"A field cannot be updated due to the current verification level or because it already has a value."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Update account","tags":["Account"],"x-product":{"wallet":"Account"}}},"/v1/account/users/person/identity":{"put":{"description":"Updates the identity document details (type, number, expiry date and country) for the\nauthenticated user.\n\nRejected if the user is already verified or has a pending verification, if the document\nis expired, or if the document number is already registered to another account.\n","requestBody":{"content":{"application/json":{"example":{"countryCode":"ES","expiryDate":"2030-06-15","number":"12345678A","type":"idcard"},"schema":{"properties":{"countryCode":{"pattern":"^[A-Z]{2}$","type":"string"},"expiryDate":{"format":"date","type":"string"},"number":{"maxLength":24,"type":"string"},"type":{"enum":["none","idcard","foreign-id-card","passport","drivinglicense","visa"],"type":"string"}},"required":["type","number","expiryDate","countryCode"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"result":true},"schema":{"properties":{"result":{"type":"boolean"}},"required":["result"],"type":"object"}}},"description":"Identity document updated."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"406":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Document is expired."},"409":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Document number already registered to another account."},"412":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"User is already verified or has a pending verification."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Update user identity document","tags":["Account"],"x-product":{"wallet":"Account"}}},"/v1/account/verify/identity":{"get":{"description":"Returns the current status of the identity verification process for the\nauthenticated user, including document images, KYC express status, risk level,\nextra measures, and tier information.\n","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"countryFormRequired":{"type":"boolean"},"disableProcess":{"type":"boolean"},"duplicatedAccountEmail":{"description":"Obfuscated email of the account that already owns the duplicated identity document. Only present when the identity error field (`error`) includes the value `number` (see ErrorsParam).","example":"mai***@gmail.com","type":"string"},"error":{"items":{"enum":["number","expiryDate","noDocUploaded","imageDoc","imageSelfie","other","unacceptableRisk","underAge","fraud","unsupportedIdType","noNationality","idCountryDiffersResidenceCountry","unsupportedIdTypeResidenceCountry","enhancedMeasuresNotReceived","pibisi","kycUpdateRequired","overAge","docDamaged","livenessCopy","docMissingImage","livenessFraud"],"type":"string"},"type":"array"},"extraMeasurePending":{"type":"boolean"},"extraMeasuresNotApproved":{"properties":{"compliance":{"items":{"enum":["MR2"],"type":"string"},"type":"array"}},"required":["compliance"],"type":"object"},"image":{"items":{"enum":["document","selfie"],"type":"string"},"type":"array"},"kycExpress":{"properties":{"status":{"enum":["success","rejected","uncompleted"],"type":"string"},"updatedAt":{"format":"date","type":"string"}},"type":"object"},"questions":{"type":"boolean"},"risk":{"properties":{"action":{"maxLength":120,"type":"string"},"level":{"enum":["undefined","low","medium","mediumHigh","high","unacceptable"],"type":"string"},"maxPoints":{"maximum":10,"minimum":0,"type":"integer"},"minPoints":{"maximum":10,"minimum":0,"type":"integer"}},"required":["level"],"type":"object"},"status":{"enum":["nodata","pending","verified","error"],"type":"string"},"subStatus":{"enum":["pending","waitingId","waitingUser"],"type":"string"},"tier":{"type":"number"},"verified":{"items":{"enum":["email","phone","identity","questions","form","admin","operator","support","support-lead","support-light","marketing","accounting","compliance","compliance-light","sales","trading","viewer","listings","api"],"type":"string"},"type":"array"}},"required":["status","image","disableProcess"],"type":"object"}}},"description":"Identity verification status."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get identity verification status","tags":["Verifier"],"x-product":{"wallet":"Account"}}},"/v1/account/verify/identity/verification/retry":{"get":{"deprecated":true,"description":"**Deprecated** — use `GET /v1/verifier/verify/identity/verification/retry` instead.\n\nRetries the identity verification process for the authenticated user.\n","responses":{"200":{"description":"Retry initiated successfully."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"406":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Retry limit exceeded."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Retry identity verification (deprecated)","tags":["Verifier Deprecated Methods"],"x-product":{"wallet":"KYC"},"x-use":"GET /v1/verifier/verify/identity/verification/retry"}},"/v1/blockchain-manager/address":{"get":{"description":"Returns the list of blockchain deposit addresses associated with a wallet pocket\non the specified network. These are the addresses generated by the platform for the user\nto receive funds, not the external addresses registered in the address book.\n\nBoth `network` and `walletPocketId` are required, and the pocket must belong to the\nauthenticated user. An empty array means the pocket has no address ready on that network;\nrequest one with `POST /v1/blockchain-manager/address`.\n","parameters":[{"description":"Network identifier (e.g. `bitcoin`, `ethereum`). It must be one of the networks supported for\nthe currency of the pocket; otherwise the response is `422`.\n","example":"bitcoin","in":"query","name":"network","required":true,"schema":{"type":"string"}},{"description":"ID of a pocket of the authenticated user.","example":"550e8400-e29b-41d4-a716-446655440002","in":"query","name":"walletPocketId","required":true,"schema":{"format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"one-address":{"summary":"A single enabled address","value":[{"address":"bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh","createdAt":"2026-06-01T10:30:00.000Z","network":"bitcoin","status":"enabled"}]},"with-tag":{"summary":"An address with a destination tag","value":[{"address":"rN7pDEfkEfMX3gHoHKhqxGHHP46GcDiXm4","createdAt":"2026-06-10T08:00:00.000Z","network":"ripple","status":"enabled","tag":"F525C9662979"}]}},"schema":{"items":{"properties":{"address":{"description":"Deposit address to send funds to. Absent while the address is still being generated.","example":"0x52908400098527886E0F7030069857D2E4169EE7","type":"string"},"createdAt":{"description":"When the address was created (ISO 8601).","example":"2026-06-01T10:30:00.000Z","format":"date-time","type":"string"},"network":{"description":"Network the address belongs to.","example":"ethereum","type":"string"},"status":{"description":"`enabled` when the address can receive funds, `pending` while it is still being generated.","enum":["enabled","pending"],"example":"enabled","type":"string"},"tag":{"description":"Destination tag or memo that must be included with every deposit to this address, on networks\nthat use one. Absent otherwise.\n","example":"F525C9662979","type":"string"}},"required":["createdAt","network","status"],"type":"object"},"type":"array"}}},"description":"Blockchain addresses for the pocket and network."},"400":{"content":{"application/json":{"example":{"error":"Bad Request","message":["walletPocketId must be a UUID"],"statusCode":400},"schema":{"description":"Returned with `400` when the request is rejected field by field rather than against the\npublished contract. It is not the same shape as the contract validation error, and the\ndifference that catches integrators out is that **`message` is an array of strings here**,\nwhile everywhere else it is a single string.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"One human-readable sentence per failed constraint.","example":["iban should not be empty","iban must be a string"],"items":{"type":"string"},"type":"array"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["message","error","statusCode"],"type":"object"}}},"description":"`network` or `walletPocketId` is missing, or `walletPocketId` is not a UUID."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"406":{"content":{"application/json":{"example":{"date":"2026-06-01T10:30:00.000Z","errorCode":"B2M_BLOCKCHAIN_MANAGER_NOT_FOUND_POCKET","errorType":"GENERIC","message":"Pocket 550e8400-e29b-41d4-a716-446655440002 not found"},"schema":{"properties":{"date":{"description":"When the error was produced (ISO 8601)","example":"2025-11-11T11:11:11.111Z","format":"date-time","type":"string"},"errorCode":{"description":"Stable, machine-readable error identifier. Branch on this, never on `message`.","example":"B2M_BLOCKCHAIN_MANAGER_TRAVEL_RULE_ORDER_NOT_FOUND","type":"string"},"errorType":{"enum":["GENERIC"],"type":"string"},"message":{"description":"Human-readable description of the error, intended for logs rather than end users.","example":"Travel rule order not found: 00000000-0000-4000-8000-000000000000","type":"string"},"requestId":{"description":"Identifier of the request that failed. Quote it when reporting an incident.","example":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd","format":"uuid","type":"string"}},"required":["errorCode","message","errorType","date"],"type":"object"}}},"description":"The pocket does not exist or does not belong to the authenticated user."},"422":{"content":{"application/json":{"examples":{"network-not-available":{"summary":"Network not available for the currency of the pocket","value":{"date":"2026-06-01T10:30:00.000Z","errorCode":"B2M_BLOCKCHAIN_MANAGER_CURRENCY_NETWORK_NOT_CONFIGURED","errorType":"GENERIC","message":"currency network not configured"}},"network-not-found":{"summary":"Unknown network","value":{"date":"2026-06-01T10:30:00.000Z","errorCode":"B2M_BLOCKCHAIN_MANAGER_NETWORK_NOT_FOUND","errorType":"GENERIC","message":"Network invalid-network not found"}}},"schema":{"properties":{"date":{"description":"When the error was produced (ISO 8601)","example":"2025-11-11T11:11:11.111Z","format":"date-time","type":"string"},"errorCode":{"description":"Stable, machine-readable error identifier. Branch on this, never on `message`.","example":"B2M_BLOCKCHAIN_MANAGER_TRAVEL_RULE_ORDER_NOT_FOUND","type":"string"},"errorType":{"enum":["GENERIC"],"type":"string"},"message":{"description":"Human-readable description of the error, intended for logs rather than end users.","example":"Travel rule order not found: 00000000-0000-4000-8000-000000000000","type":"string"},"requestId":{"description":"Identifier of the request that failed. Quote it when reporting an incident.","example":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd","format":"uuid","type":"string"}},"required":["errorCode","message","errorType","date"],"type":"object"}}},"description":"The network is unknown (`B2M_BLOCKCHAIN_MANAGER_NETWORK_NOT_FOUND`), or it is not available for\nthe currency of the pocket (`B2M_BLOCKCHAIN_MANAGER_CURRENCY_NETWORK_NOT_CONFIGURED`).\n"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Find blockchain addresses","tags":["Blockchain Manager"],"x-product":{"wallet":"Funding"}},"post":{"description":"Generates a new blockchain deposit address for the given network and wallet pocket. The pocket\nmust belong to the authenticated user.\n\nThe address may not be ready immediately: with `status: pending` it is still being generated,\nand it shows up with its `address` in `GET /v1/blockchain-manager/address` once ready.\n","requestBody":{"content":{"application/json":{"example":{"network":"bitcoin","walletPocketId":"550e8400-e29b-41d4-a716-446655440002"},"schema":{"properties":{"network":{"description":"Network identifier (e.g. `bitcoin`, `ethereum`). It must be one of the networks\nsupported for the currency of the pocket.\n","example":"bitcoin","type":"string"},"walletPocketId":{"description":"ID of a pocket of the authenticated user.","example":"550e8400-e29b-41d4-a716-446655440002","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}},"required":["network","walletPocketId"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"example":{"status":"enabled"},"schema":{"properties":{"status":{"description":"State of the deposit address. With `enabled` it is ready to receive funds. With `pending` it\nis still being generated; list the addresses of the pocket again later to get it.\n","enum":["enabled","pending"],"example":"enabled","type":"string"}},"required":["status"],"type":"object"}}},"description":"Address requested."},"400":{"content":{"application/json":{"example":{"error":"Bad Request","message":["network must be a string"],"statusCode":400},"schema":{"description":"Returned with `400` when the request is rejected field by field rather than against the\npublished contract. It is not the same shape as the contract validation error, and the\ndifference that catches integrators out is that **`message` is an array of strings here**,\nwhile everywhere else it is a single string.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"One human-readable sentence per failed constraint.","example":["iban should not be empty","iban must be a string"],"items":{"type":"string"},"type":"array"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["message","error","statusCode"],"type":"object"}}},"description":"`network` or `walletPocketId` is missing, or `walletPocketId` is not a UUID."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"406":{"content":{"application/json":{"example":{"date":"2026-06-01T10:30:00.000Z","errorCode":"B2M_BLOCKCHAIN_MANAGER_NOT_FOUND_POCKET","errorType":"GENERIC","message":"Pocket 550e8400-e29b-41d4-a716-446655440002 not found"},"schema":{"properties":{"date":{"description":"When the error was produced (ISO 8601)","example":"2025-11-11T11:11:11.111Z","format":"date-time","type":"string"},"errorCode":{"description":"Stable, machine-readable error identifier. Branch on this, never on `message`.","example":"B2M_BLOCKCHAIN_MANAGER_TRAVEL_RULE_ORDER_NOT_FOUND","type":"string"},"errorType":{"enum":["GENERIC"],"type":"string"},"message":{"description":"Human-readable description of the error, intended for logs rather than end users.","example":"Travel rule order not found: 00000000-0000-4000-8000-000000000000","type":"string"},"requestId":{"description":"Identifier of the request that failed. Quote it when reporting an incident.","example":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd","format":"uuid","type":"string"}},"required":["errorCode","message","errorType","date"],"type":"object"}}},"description":"The pocket does not exist or does not belong to the authenticated user."},"422":{"content":{"application/json":{"examples":{"network-not-available":{"summary":"Network not available for the currency of the pocket","value":{"date":"2026-06-01T10:30:00.000Z","errorCode":"B2M_BLOCKCHAIN_MANAGER_CURRENCY_NETWORK_NOT_CONFIGURED","errorType":"GENERIC","message":"currency network not configured"}},"network-not-found":{"summary":"Unknown network","value":{"date":"2026-06-01T10:30:00.000Z","errorCode":"B2M_BLOCKCHAIN_MANAGER_NETWORK_NOT_FOUND","errorType":"GENERIC","message":"Network invalid-network not found"}}},"schema":{"properties":{"date":{"description":"When the error was produced (ISO 8601)","example":"2025-11-11T11:11:11.111Z","format":"date-time","type":"string"},"errorCode":{"description":"Stable, machine-readable error identifier. Branch on this, never on `message`.","example":"B2M_BLOCKCHAIN_MANAGER_TRAVEL_RULE_ORDER_NOT_FOUND","type":"string"},"errorType":{"enum":["GENERIC"],"type":"string"},"message":{"description":"Human-readable description of the error, intended for logs rather than end users.","example":"Travel rule order not found: 00000000-0000-4000-8000-000000000000","type":"string"},"requestId":{"description":"Identifier of the request that failed. Quote it when reporting an incident.","example":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd","format":"uuid","type":"string"}},"required":["errorCode","message","errorType","date"],"type":"object"}}},"description":"The network is unknown (`B2M_BLOCKCHAIN_MANAGER_NETWORK_NOT_FOUND`), or it is not available for\nthe currency of the pocket (`B2M_BLOCKCHAIN_MANAGER_CURRENCY_NETWORK_NOT_CONFIGURED`).\n"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Create a blockchain address","tags":["Blockchain Manager"],"x-product":{"wallet":"Funding"}}},"/v1/blockchain-manager/address-book":{"get":{"description":"Returns the user's registered external blockchain addresses, optionally filtered by currency\nor network.\n\nOnly entries in `validating` or `verified` state are returned. Entries in `validating` state are\nwaiting for the user to confirm an authorization email; only `verified` ones are ready for\nwithdrawals.\n","parameters":[{"description":"Only return entries for this currency symbol.","example":"BTC","in":"query","name":"currency","schema":{"minLength":1,"type":"string"}},{"description":"Only return entries on this network.","example":"bitcoin","in":"query","name":"network","schema":{"minLength":1,"type":"string"}},{"description":"Verification status. It is validated against the allowed values but does not filter the\nresult: the list always contains the `validating` and `verified` entries.\n","example":"verified","in":"query","name":"status","schema":{"enum":["validating","verified","expired","disabled"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"two-entries":{"summary":"Two verified entries, one with a tag","value":[{"address":"bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh","addressId":"550e8400-e29b-41d4-a716-446655440000","createdAt":"2026-06-01T10:30:00.000Z","currency":"BTC","exchangeName":"Binance","name":"John","network":"bitcoin","personType":"person","status":"verified","surname":"Doe","updatedAt":"2026-06-01T10:35:00.000Z","userId":"550e8400-e29b-41d4-a716-446655440099","walletOwnership":"other","walletType":"exchange"},{"address":"rN7pDEfkEfMX3gHoHKhqxGHHP46GcDiXm4","addressId":"550e8400-e29b-41d4-a716-446655440001","createdAt":"2026-06-10T08:00:00.000Z","currency":"XRP","network":"ripple","status":"verified","tag":"123456","updatedAt":"2026-06-10T08:05:00.000Z","userId":"550e8400-e29b-41d4-a716-446655440099","walletOwnership":"own","walletType":"unhosted"}]}},"schema":{"items":{"properties":{"address":{"description":"The registered blockchain address.","example":"bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh","type":"string"},"addressId":{"description":"Unique identifier of the address book entry.","example":"550e8400-e29b-41d4-a716-446655440000","format":"uuid","type":"string"},"createdAt":{"description":"When the entry was created (ISO 8601).","example":"2026-06-01T10:30:00.000Z","format":"date-time","type":"string"},"currency":{"description":"Symbol of the cryptocurrency the address is registered for.","example":"BTC","type":"string"},"exchangeName":{"description":"Name of the exchange. Absent when it was not provided.","example":"Binance","type":"string"},"name":{"description":"First name of the beneficiary, or the company name. Absent when it was not provided.","example":"John","type":"string"},"network":{"description":"Network of the address.","example":"bitcoin","type":"string"},"personType":{"description":"Whether the beneficiary is a natural person or a company. Absent when it was not provided.","enum":["company","person"],"example":"person","type":"string"},"status":{"description":"Current verification state of the entry. A newly created entry starts in `validating`\nand moves to `verified` after the user confirms the authorization email. `expired` means\nthe confirmation window closed without action; `disabled` means the entry was deactivated.\nThe list and detail operations only return `validating` and `verified` entries.\n","enum":["validating","verified","expired","disabled"],"example":"verified","type":"string"},"surname":{"description":"Last name of the beneficiary. Absent when it was not provided.","example":"Doe","type":"string"},"tag":{"description":"Destination tag or memo. Absent when the entry has none.","example":"123456","type":"string"},"updatedAt":{"description":"When the entry was last modified (ISO 8601).","example":"2026-06-01T10:35:00.000Z","format":"date-time","type":"string"},"userId":{"description":"ID of the user who owns the entry.","example":"550e8400-e29b-41d4-a716-446655440001","format":"uuid","type":"string"},"walletOwnership":{"description":"Whether the wallet belongs to the same user or to someone else.","enum":["other","own"],"example":"other","type":"string"},"walletType":{"description":"Whether the destination is a hosted exchange wallet or an unhosted (self-custody) wallet.","enum":["exchange","unhosted"],"example":"exchange","type":"string"}},"required":["addressId","userId","address","currency","network","status","walletType","walletOwnership","createdAt","updatedAt"],"type":"object"},"type":"array"}}},"description":"Address book entries matching the filters (empty array when none match)."},"400":{"content":{"application/json":{"example":{"error":"Bad Request","message":["status must be one of the following values: validating, verified, expired, disabled"],"statusCode":400},"schema":{"description":"Returned with `400` when the request is rejected field by field rather than against the\npublished contract. It is not the same shape as the contract validation error, and the\ndifference that catches integrators out is that **`message` is an array of strings here**,\nwhile everywhere else it is a single string.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"One human-readable sentence per failed constraint.","example":["iban should not be empty","iban must be a string"],"items":{"type":"string"},"type":"array"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["message","error","statusCode"],"type":"object"}}},"description":"`status` is not one of the allowed values, or `currency` or `network` is empty."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials — the API key, signature or nonce could not be validated."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"List address book entries","tags":["Blockchain Manager"],"x-product":{"wallet":"Funding"}},"post":{"description":"Registers a new external blockchain address in the user's address book for future withdrawals.\n\nThe entry starts in `validating` state. An authorization email is sent to the user; the entry\nmoves to `verified` only after the user confirms it. Real-time status updates arrive through\nthe websocket event `address-book-updated-v1`.\n\nThe address is checked against the format of `network`, and the same address cannot be\nregistered twice for the same currency and network while an earlier entry is still\n`validating` or `verified`.\n","requestBody":{"content":{"application/json":{"examples":{"exchange-other":{"summary":"Address at an exchange, owned by someone else","value":{"address":"bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh","currency":"BTC","exchangeName":"Binance","name":"John","network":"bitcoin","personType":"person","surname":"Doe","walletOwnership":"other","walletType":"exchange"}},"unhosted-own":{"summary":"Self-custody wallet, owned by the caller","value":{"address":"rN7pDEfkEfMX3gHoHKhqxGHHP46GcDiXm4","currency":"XRP","network":"ripple","ownershipVerified":true,"tag":"123456","walletOwnership":"own","walletType":"unhosted"}}},"schema":{"properties":{"address":{"description":"The blockchain address to register. Surrounding spaces are trimmed and no whitespace is\nallowed inside. It must be a valid address for `network`.\n","example":"bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh","minLength":1,"pattern":"^\\S+$","type":"string"},"currency":{"description":"Symbol of the cryptocurrency that will be withdrawn to the address.","example":"BTC","minLength":1,"type":"string"},"exchangeName":{"description":"Name of the exchange. Send it when `walletType` is `exchange`.","example":"Binance","type":"string"},"name":{"description":"First name of the beneficiary, or the company name when `personType` is `company`. Send it\nwhen `walletOwnership` is `other`.\n","example":"John","type":"string"},"network":{"description":"Network of the address. It must be one of the networks supported for `currency`.","example":"bitcoin","minLength":1,"type":"string"},"ownershipVerified":{"description":"The user's statement that they control the destination wallet (proof of ownership). Only\ntaken into account when `walletType` is `unhosted`.\n","example":true,"type":"boolean"},"personType":{"description":"Whether the beneficiary is a natural person or a company. Send it when `walletOwnership` is `other`.","enum":["company","person"],"example":"person","type":"string"},"surname":{"description":"Last name of the beneficiary. Send it when `personType` is `person`.","example":"Doe","type":"string"},"tag":{"description":"Destination tag or memo, for networks that use one (e.g. XRP, XLM). Rejected on networks that\ndo not support it.\n","example":"123456","minLength":1,"type":"string"},"walletOwnership":{"description":"Whether the destination wallet belongs to the same user (`own`) or to someone else (`other`).","enum":["other","own"],"example":"other","type":"string"},"walletType":{"description":"Whether the destination is a hosted exchange wallet or an unhosted (self-custody) wallet.","enum":["exchange","unhosted"],"example":"exchange","type":"string"}},"required":["address","currency","network","walletType","walletOwnership"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"example":{"address":"bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh","addressId":"550e8400-e29b-41d4-a716-446655440000","createdAt":"2026-06-01T10:30:00.000Z","currency":"BTC","exchangeName":"Binance","name":"John","network":"bitcoin","personType":"person","status":"validating","surname":"Doe","updatedAt":"2026-06-01T10:30:00.000Z","userId":"550e8400-e29b-41d4-a716-446655440099","walletOwnership":"other","walletType":"exchange"},"schema":{"properties":{"address":{"description":"The registered blockchain address.","example":"bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh","type":"string"},"addressId":{"description":"Unique identifier of the address book entry.","example":"550e8400-e29b-41d4-a716-446655440000","format":"uuid","type":"string"},"createdAt":{"description":"When the entry was created (ISO 8601).","example":"2026-06-01T10:30:00.000Z","format":"date-time","type":"string"},"currency":{"description":"Symbol of the cryptocurrency the address is registered for.","example":"BTC","type":"string"},"exchangeName":{"description":"Name of the exchange. Absent when it was not provided.","example":"Binance","type":"string"},"name":{"description":"First name of the beneficiary, or the company name. Absent when it was not provided.","example":"John","type":"string"},"network":{"description":"Network of the address.","example":"bitcoin","type":"string"},"personType":{"description":"Whether the beneficiary is a natural person or a company. Absent when it was not provided.","enum":["company","person"],"example":"person","type":"string"},"status":{"description":"Current verification state of the entry. A newly created entry starts in `validating`\nand moves to `verified` after the user confirms the authorization email. `expired` means\nthe confirmation window closed without action; `disabled` means the entry was deactivated.\nThe list and detail operations only return `validating` and `verified` entries.\n","enum":["validating","verified","expired","disabled"],"example":"verified","type":"string"},"surname":{"description":"Last name of the beneficiary. Absent when it was not provided.","example":"Doe","type":"string"},"tag":{"description":"Destination tag or memo. Absent when the entry has none.","example":"123456","type":"string"},"updatedAt":{"description":"When the entry was last modified (ISO 8601).","example":"2026-06-01T10:35:00.000Z","format":"date-time","type":"string"},"userId":{"description":"ID of the user who owns the entry.","example":"550e8400-e29b-41d4-a716-446655440001","format":"uuid","type":"string"},"walletOwnership":{"description":"Whether the wallet belongs to the same user or to someone else.","enum":["other","own"],"example":"other","type":"string"},"walletType":{"description":"Whether the destination is a hosted exchange wallet or an unhosted (self-custody) wallet.","enum":["exchange","unhosted"],"example":"exchange","type":"string"}},"required":["addressId","userId","address","currency","network","status","walletType","walletOwnership","createdAt","updatedAt"],"type":"object"}}},"description":"Address book entry created. It starts in `validating` state."},"400":{"content":{"application/json":{"examples":{"not-configured":{"summary":"Currency not available on the network","value":{"error":"Bad Request","message":"Currency BTC and network ethereum are not configured","statusCode":400}},"tag-not-allowed":{"summary":"Tag sent for a network without tags","value":{"error":"Bad Request","message":"Tag is not allowed for this network","statusCode":400}},"validation":{"summary":"Invalid value for `walletType`","value":{"error":"Bad Request","message":["walletType must be one of the following values: exchange, unhosted"],"statusCode":400}}},"schema":{"oneOf":[{"description":"Returned with `400` when the request is rejected field by field rather than against the\npublished contract. It is not the same shape as the contract validation error, and the\ndifference that catches integrators out is that **`message` is an array of strings here**,\nwhile everywhere else it is a single string.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"One human-readable sentence per failed constraint.","example":["iban should not be empty","iban must be a string"],"items":{"type":"string"},"type":"array"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["message","error","statusCode"],"type":"object"},{"description":"Business error returned by the operation.","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Address book 550e8400-e29b-41d4-a716-446655440000 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message"],"type":"object"}]}}},"description":"The body is malformed (`FieldValidationErrorResponse`, with `message` as an array), or its\nvalues are rejected (`BlockchainManagerErrorResponse`, with `message` as a string): the\ncurrency or network does not exist, the currency is not available on that network, the\naddress is not valid for the network, or a `tag` was sent for a network that does not use one.\n"},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"409":{"content":{"application/json":{"example":{"error":"Conflict","message":"Address bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh already exists for this user with an active status","statusCode":409},"schema":{"description":"Business error returned by the operation.","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Address book 550e8400-e29b-41d4-a716-446655440000 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"The address is already registered for this currency and network in `validating` or `verified` state."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Create an address book entry","tags":["Blockchain Manager"],"x-product":{"wallet":"Funding"}}},"/v1/blockchain-manager/address-book/{addressId}":{"get":{"description":"Returns the details of a single address book entry of the authenticated user, identified by its\nUUID. Only entries in `validating` or `verified` state can be retrieved.\n","parameters":[{"description":"UUID of the address book entry.","example":"550e8400-e29b-41d4-a716-446655440000","in":"path","name":"addressId","required":true,"schema":{"format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"address":"bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh","addressId":"550e8400-e29b-41d4-a716-446655440000","createdAt":"2026-06-01T10:30:00.000Z","currency":"BTC","exchangeName":"Binance","name":"John","network":"bitcoin","personType":"person","status":"verified","surname":"Doe","updatedAt":"2026-06-01T10:35:00.000Z","userId":"550e8400-e29b-41d4-a716-446655440099","walletOwnership":"other","walletType":"exchange"},"schema":{"properties":{"address":{"description":"The registered blockchain address.","example":"bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh","type":"string"},"addressId":{"description":"Unique identifier of the address book entry.","example":"550e8400-e29b-41d4-a716-446655440000","format":"uuid","type":"string"},"createdAt":{"description":"When the entry was created (ISO 8601).","example":"2026-06-01T10:30:00.000Z","format":"date-time","type":"string"},"currency":{"description":"Symbol of the cryptocurrency the address is registered for.","example":"BTC","type":"string"},"exchangeName":{"description":"Name of the exchange. Absent when it was not provided.","example":"Binance","type":"string"},"name":{"description":"First name of the beneficiary, or the company name. Absent when it was not provided.","example":"John","type":"string"},"network":{"description":"Network of the address.","example":"bitcoin","type":"string"},"personType":{"description":"Whether the beneficiary is a natural person or a company. Absent when it was not provided.","enum":["company","person"],"example":"person","type":"string"},"status":{"description":"Current verification state of the entry. A newly created entry starts in `validating`\nand moves to `verified` after the user confirms the authorization email. `expired` means\nthe confirmation window closed without action; `disabled` means the entry was deactivated.\nThe list and detail operations only return `validating` and `verified` entries.\n","enum":["validating","verified","expired","disabled"],"example":"verified","type":"string"},"surname":{"description":"Last name of the beneficiary. Absent when it was not provided.","example":"Doe","type":"string"},"tag":{"description":"Destination tag or memo. Absent when the entry has none.","example":"123456","type":"string"},"updatedAt":{"description":"When the entry was last modified (ISO 8601).","example":"2026-06-01T10:35:00.000Z","format":"date-time","type":"string"},"userId":{"description":"ID of the user who owns the entry.","example":"550e8400-e29b-41d4-a716-446655440001","format":"uuid","type":"string"},"walletOwnership":{"description":"Whether the wallet belongs to the same user or to someone else.","enum":["other","own"],"example":"other","type":"string"},"walletType":{"description":"Whether the destination is a hosted exchange wallet or an unhosted (self-custody) wallet.","enum":["exchange","unhosted"],"example":"exchange","type":"string"}},"required":["addressId","userId","address","currency","network","status","walletType","walletOwnership","createdAt","updatedAt"],"type":"object"}}},"description":"Address book entry details."},"400":{"content":{"application/json":{"example":{"error":"Bad Request","message":"Validation failed (uuid is expected)","statusCode":400},"schema":{"description":"Business error returned by the operation.","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Address book 550e8400-e29b-41d4-a716-446655440000 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"`addressId` is not a UUID."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"example":{"error":"Not Found","message":"Address book 550e8400-e29b-41d4-a716-446655440000 not found","statusCode":404},"schema":{"description":"Business error returned by the operation.","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Address book 550e8400-e29b-41d4-a716-446655440000 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"No entry exists with this identifier for the authenticated user, or it is no longer in\n`validating` or `verified` state.\n"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get address book entry","tags":["Blockchain Manager"],"x-product":{"wallet":"Funding"}}},"/v1/blockchain-manager/order/withdrawal/draft":{"post":{"description":"Creates a draft withdrawal order that must be accepted before it is submitted to the\nblockchain. The draft takes the destination address, network, tag and fees from the address\nbook entry referenced by `addressBookId`, and debits the user's pocket of that currency with the\nhighest balance; the caller only specifies how much to withdraw, either in the cryptocurrency or\nin a fiat currency.\n\nChecks the balance (including the network fee), the minimum amount for the network and that the\nuser is allowed to withdraw. Nothing is debited yet. The draft expires at `expiresAt`; after that\nit cannot be accepted and a new one has to be created.\n","requestBody":{"content":{"application/json":{"examples":{"crypto":{"summary":"Amount in the cryptocurrency","value":{"addressBookId":"550e8400-e29b-41d4-a716-446655440000","amount":{"currency":"BTC","value":"0.5"}}},"fiat":{"summary":"Amount in EUR","value":{"addressBookId":"550e8400-e29b-41d4-a716-446655440000","amount":{"currency":"EUR","value":"475"}}}},"schema":{"description":"Request to create a withdrawal draft. The destination address, network, tag, source pocket\nand fees are taken from the address book entry referenced by `addressBookId`.\nThe caller only specifies how much to withdraw.\n","properties":{"addressBookId":{"description":"ID of one of the user's address book entries, the destination of the withdrawal.","example":"550e8400-e29b-41d4-a716-446655440000","format":"uuid","type":"string"},"amount":{"description":"How much to withdraw. It can be given in the cryptocurrency of the address book entry, or in a\nfiat currency, in which case it is converted at the current price.\n","properties":{"currency":{"description":"Symbol of the currency of `value`: either the cryptocurrency of the address book entry or a\nfiat currency such as `EUR`. Any other cryptocurrency is rejected.\n","example":"BTC","minLength":1,"type":"string"},"value":{"description":"Amount as a decimal string.","example":"0.5","minLength":1,"type":"string"}},"required":["value","currency"],"type":"object"}},"required":["amount","addressBookId"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"examples":{"crypto":{"summary":"Amount requested in the cryptocurrency","value":{"addressBookId":"550e8400-e29b-41d4-a716-446655440000","amount":"0.5","currency":"BTC","denomination":{"amount":"0.5","currency":"BTC","price":"1"},"destinationAddress":"bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh","draftId":"550e8400-e29b-41d4-a716-446655440010","expiresAt":"2026-06-02T12:00:30.000Z","network":"bitcoin","networkFee":"0.0001","tag":null,"totalAmount":"0.5001","walletPocketId":"550e8400-e29b-41d4-a716-446655440002"}},"fiat":{"summary":"Amount requested in EUR","value":{"addressBookId":"550e8400-e29b-41d4-a716-446655440000","amount":"0.005","currency":"BTC","denomination":{"amount":"475","currency":"EUR","price":"95000"},"destinationAddress":"bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh","draftId":"550e8400-e29b-41d4-a716-446655440011","expiresAt":"2026-06-02T12:00:30.000Z","network":"bitcoin","networkFee":"0.0001","tag":null,"totalAmount":"0.0051","walletPocketId":"550e8400-e29b-41d4-a716-446655440002"}}},"schema":{"description":"A draft withdrawal order. The draft has an expiration time; if not accepted before it expires,\nit is discarded and the caller must create a new one.\n","properties":{"addressBookId":{"description":"Address book entry the draft resolves to.","example":"550e8400-e29b-41d4-a716-446655440001","format":"uuid","type":"string"},"amount":{"description":"Amount that will be sent to the destination, in `currency`, as a decimal string.","example":"0.5","type":"string"},"currency":{"description":"Currency symbol.","example":"BTC","type":"string"},"denomination":{"description":"The amount as it was requested, and the price used to convert it to the cryptocurrency.","properties":{"amount":{"description":"The requested `amount.value`.","example":"0.5","type":"string"},"currency":{"description":"The requested `amount.currency`.","example":"BTC","type":"string"},"price":{"description":"Price of one unit of the cryptocurrency in `currency`. It is `1` when the amount was requested\nin the cryptocurrency itself.\n","example":"1","type":"string"}},"required":["amount","currency","price"],"type":"object"},"destinationAddress":{"description":"Blockchain address the funds will be sent to.","example":"bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh","type":"string"},"draftId":{"description":"Unique identifier of the draft, needed to accept it.","example":"550e8400-e29b-41d4-a716-446655440000","format":"uuid","type":"string"},"expiresAt":{"description":"When the draft expires (ISO 8601). After this point it cannot be accepted.","example":"2026-06-02T12:00:30.000Z","format":"date-time","type":"string"},"network":{"description":"Network identifier.","example":"bitcoin","type":"string"},"networkFee":{"description":"Network fee charged for the transaction, as a decimal string.","example":"0.0001","type":"string"},"tag":{"description":"Destination tag or memo, `null` when the address book entry has none.","example":"123456","nullable":true,"type":"string"},"totalAmount":{"description":"Total debited from the pocket (`amount` + `networkFee`), as a decimal string.","example":"0.5001","type":"string"},"walletPocketId":{"description":"Source pocket the funds will be debited from: the user's pocket of `currency` with the highest\nbalance.\n","example":"550e8400-e29b-41d4-a716-446655440002","format":"uuid","type":"string"}},"required":["draftId","expiresAt","addressBookId","walletPocketId","amount","networkFee","totalAmount","currency","network","destinationAddress","denomination"],"type":"object"}}},"description":"Withdrawal draft created. Accept it before `expiresAt` to submit the withdrawal."},"400":{"content":{"application/json":{"examples":{"invalid-currency":{"summary":"Amount in a different cryptocurrency","value":{"error":"Bad Request","message":"invalid amount currency ETH","statusCode":400}},"validation":{"summary":"Missing `addressBookId`","value":{"error":"Bad Request","message":["addressBookId must be a UUID"],"statusCode":400}}},"schema":{"oneOf":[{"description":"Returned with `400` when the request is rejected field by field rather than against the\npublished contract. It is not the same shape as the contract validation error, and the\ndifference that catches integrators out is that **`message` is an array of strings here**,\nwhile everywhere else it is a single string.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"One human-readable sentence per failed constraint.","example":["iban should not be empty","iban must be a string"],"items":{"type":"string"},"type":"array"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["message","error","statusCode"],"type":"object"},{"description":"Business error returned by the operation.","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Address book 550e8400-e29b-41d4-a716-446655440000 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message"],"type":"object"}]}}},"description":"The body is malformed (`FieldValidationErrorResponse`, with `message` as an array), or the\nwithdrawal is not possible as requested (`BlockchainManagerErrorResponse`): `amount.currency`\nis a cryptocurrency other than the one of the address book entry, or withdrawals of that\ncurrency are not available on the network of the entry.\n"},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"example":{"error":"Not Found","message":"Address book 550e8400-e29b-41d4-a716-446655440000 not found","statusCode":404},"schema":{"description":"Business error returned by the operation.","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Address book 550e8400-e29b-41d4-a716-446655440000 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"The address book entry does not exist or does not belong to the user."},"412":{"content":{"application/json":{"example":{"message":"withdrawal is blocked","statusCode":412},"schema":{"description":"Business error from the withdrawal draft operation. For `417` below the minimum, `message` states\nthe minimum amount, e.g. `Withdrawal amount is below the minimum of 5 USDC`; there is no\nstructured field with it.\n","properties":{"message":{"description":"Human-readable description of the rejection.","example":"Withdrawal amount is below the minimum of 5 USDC","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":417,"type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"Withdrawals are blocked for the user. Retrying the same request does not help."},"417":{"content":{"application/json":{"examples":{"below-minimum":{"summary":"Amount below the network minimum","value":{"message":"Withdrawal amount is below the minimum of 5 USDC","statusCode":417}},"insufficient-balance":{"summary":"Not enough balance in the pocket to cover the amount and the network fee","value":{"message":"Insufficient balance for withdrawal including network fee","statusCode":417}}},"schema":{"description":"Business error from the withdrawal draft operation. For `417` below the minimum, `message` states\nthe minimum amount, e.g. `Withdrawal amount is below the minimum of 5 USDC`; there is no\nstructured field with it.\n","properties":{"message":{"description":"Human-readable description of the rejection.","example":"Withdrawal amount is below the minimum of 5 USDC","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":417,"type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"Withdrawal below the network minimum or insufficient balance. When the cause is a minimum\nviolation, `message` contains the minimum in natural language\n(e.g. `Withdrawal amount is below the minimum of 5 USDC`). The minimum is **not** in a\nstructured field.\n"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Create a withdrawal draft","tags":["Blockchain Manager"],"x-product":{"wallet":"Funding"}}},"/v1/blockchain-manager/order/withdrawal/draft/accept":{"post":{"description":"Confirms and submits a previously created withdrawal draft, creating the actual withdrawal\norder on the blockchain. The draft must belong to the authenticated user and must not have\nexpired.\n\nEvery acceptance requires a second-factor code in the `x-totp` header. The first request is\nusually sent without it and answered with `428`:\n* For stablecoin withdrawals, the `428` means a code has just been sent to the user, and its body\n  says through which channel (`sfaType`) and which phone channels are available\n  (`availableChannels`, `defaultChannel`).\n* For any other currency, the `428` only says that the code is needed.\n\nThen repeat the same request with the code in `x-totp` and the channel it came through in\n`x-totp-type`. A wrong code returns `420` and nothing is executed.\n","parameters":[{"description":"Second-factor code. Without it the response is `428`.","example":"123456","in":"header","name":"x-totp","schema":{"description":"4-6 digit TOTP verification code","example":"123456","pattern":"^[0-9]{4,6}$","type":"string"}},{"description":"Channel through which the code in `x-totp` was received (e.g. `sms`, `whatsapp`, `email`, `gauth`).","example":"sms","in":"header","name":"x-totp-type","schema":{"enum":["gauth","sms","email","call","whatsapp"],"type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"draftId":"550e8400-e29b-41d4-a716-446655440010"},"schema":{"description":"Request to accept (confirm) a previously created withdrawal draft.","properties":{"draftId":{"description":"Identifier of the draft to accept.","example":"550e8400-e29b-41d4-a716-446655440000","format":"uuid","type":"string"}},"required":["draftId"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"example":{"amount":"0.5","chargedFee":"0.0001","chargedFeeCurrency":"BTC","createdAt":"2026-06-02T12:00:00.000Z","currency":"BTC","destinationAddress":"bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh","network":"bitcoin","orderId":"550e8400-e29b-41d4-a716-446655440020","status":"created","tag":null,"type":"withdrawal","userId":"550e8400-e29b-41d4-a716-446655440099","walletPocketId":"550e8400-e29b-41d4-a716-446655440002"},"schema":{"description":"The withdrawal order created after accepting a draft.","properties":{"amount":{"description":"Net amount of the withdrawal, as a decimal string.","example":"1.5","type":"string"},"chargedFee":{"description":"Fee charged for the withdrawal, as a decimal string.","example":"0.0001","type":"string"},"chargedFeeCurrency":{"description":"Currency of the charged fee.","example":"BTC","type":"string"},"createdAt":{"description":"When the order was created (ISO 8601).","example":"2026-06-02T12:00:00.000Z","format":"date-time","type":"string"},"currency":{"description":"Currency symbol.","example":"BTC","type":"string"},"destinationAddress":{"description":"Blockchain address the funds are sent to.","example":"bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh","type":"string"},"network":{"description":"Network identifier.","example":"bitcoin","type":"string"},"orderId":{"description":"Unique identifier of the withdrawal order.","example":"550e8400-e29b-41d4-a716-446655440000","format":"uuid","type":"string"},"status":{"description":"Current state of the order. Only `completed`, `canceled`, `error` and `rejected` are\nterminal; every other value means the order is still in flight.\n","enum":["completed","created","canceled","compliance-reviewing","error","operations-reviewing","pending-compliance-review","pending-operations-review","pending-user-information","pending-risk-analysis","pending-review","pending-verification","processing","rejected","reviewing"],"example":"created","type":"string"},"tag":{"description":"Destination tag or memo, `null` when the destination has none.","example":"123456","nullable":true,"type":"string"},"type":{"description":"Direction of the order. Always `withdrawal` here.","enum":["deposit","withdrawal"],"example":"withdrawal","type":"string"},"userId":{"description":"ID of the user who owns the order.","example":"550e8400-e29b-41d4-a716-446655440099","format":"uuid","type":"string"},"walletPocketId":{"description":"Source pocket the funds were debited from.","example":"550e8400-e29b-41d4-a716-446655440002","format":"uuid","type":"string"}},"required":["orderId","type","status","amount","currency","network","destinationAddress","chargedFee","chargedFeeCurrency","walletPocketId","userId","createdAt"],"type":"object"}}},"description":"Withdrawal order created and submitted to the blockchain."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"example":{"error":"Not Found","message":"Withdrawal draft 550e8400-e29b-41d4-a716-446655440010 not found","statusCode":404},"schema":{"description":"Business error returned by the operation.","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Address book 550e8400-e29b-41d4-a716-446655440000 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"The withdrawal draft does not exist, has expired or was already accepted, or its address book\nentry no longer exists. Create a new draft.\n"},"420":{"content":{"application/json":{"examples":{"other":{"summary":"Any other currency","value":{"message":"2FA TOTP doesn't match"}},"stablecoin":{"summary":"Stablecoin withdrawal","value":{"data":{"sfaProcessInitialized":true,"sfaType":"sms"},"message":"2FA TOTP doesn't match"}}},"schema":{"description":"Returned with `420` when the code in `x-totp` is not valid. Nothing is executed. For stablecoin\nwithdrawals `data` is present and a new code can be sent by repeating the request without\n`x-totp`.\n","properties":{"data":{"description":"Second-factor state. Only for stablecoin withdrawals.","properties":{"sfaProcessInitialized":{"description":"Always `true`.","example":true,"type":"boolean"},"sfaType":{"allOf":[{"enum":["gauth","sms","email","call","whatsapp"],"type":"string"}],"description":"Channel sent in `x-totp-type`. Absent when the header was not sent.","example":"sms"}},"required":["sfaProcessInitialized"],"type":"object"},"message":{"description":"Always `2FA TOTP doesn't match`.","example":"2FA TOTP doesn't match","type":"string"},"statusCode":{"description":"Repeats the HTTP status code, when present.","enum":[420],"example":420,"type":"integer"}},"required":["message"],"type":"object"}}},"description":"The code in `x-totp` is not valid. Nothing is executed."},"428":{"content":{"application/json":{"examples":{"other":{"summary":"Any other currency","value":{"message":"2FA TOTP is required","statusCode":428}},"stablecoin":{"summary":"Stablecoin withdrawal, code sent by SMS","value":{"availableChannels":["sms","whatsapp"],"defaultChannel":"sms","message":"2FA TOTP is required","retryIntervalSeconds":60,"sfaProcessInitialized":true,"sfaType":"sms"}}},"schema":{"description":"Returned with `428` when the request has no `x-totp` header. Repeat the same `POST` with the\ncode in `x-totp` (and its channel in `x-totp-type`).\n\nFor stablecoin withdrawals a code is sent to the user right away and the response describes how\nit was sent: `sfaProcessInitialized` and the rest of the optional fields are only present in that\ncase. For any other currency the response only has `statusCode` and `message`.\n","properties":{"availableChannels":{"description":"Phone channels the user can receive the code through.","example":["sms","whatsapp"],"items":{"description":"Phone channel through which the second-factor code can be delivered.","enum":["sms","call","whatsapp"],"example":"sms","type":"string"},"type":"array"},"defaultChannel":{"allOf":[{"description":"Phone channel through which the second-factor code can be delivered.","enum":["sms","call","whatsapp"],"example":"sms","type":"string"}],"description":"Phone channel used by default.","example":"sms"},"message":{"description":"Always `2FA TOTP is required`.","example":"2FA TOTP is required","type":"string"},"retryIntervalSeconds":{"description":"Seconds to wait before a new code can be requested through the same phone channel.","example":60,"minimum":0,"type":"integer"},"sfaProcessInitialized":{"description":"`true` when a code has just been sent to the user.","example":true,"type":"boolean"},"sfaType":{"allOf":[{"enum":["gauth","sms","email","call","whatsapp"],"type":"string"}],"description":"Channel the code was sent through. Send the same value in `x-totp-type`.","example":"sms"},"statusCode":{"description":"Repeats the HTTP status code. Absent when a code was sent for a stablecoin withdrawal.","enum":[428],"example":428,"type":"integer"}},"required":["message"],"type":"object"}}},"description":"No `x-totp` was sent. Repeat the same request with the code. For stablecoin withdrawals a\ncode has just been sent and the body says how.\n"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Accept a withdrawal draft","tags":["Blockchain Manager"],"x-product":{"wallet":"Funding"}}},"/v1/blockchain-manager/travel-rule-order/{orderId}":{"post":{"deprecated":true,"description":"**Deprecated** — use `POST /v2/blockchain-manager/travel-rule-order/{orderId}` instead.\n\nSubmits the travel-rule information of a crypto order of the authenticated user: who the\ncounterparty is and what kind of wallet they use. For a deposit that is who sent the funds, and\nfor a withdrawal who receives them. This version also accepts the counterparty's identity\ndocument, full postal address, place of birth and date of birth.\n\nWhen `walletOwnership` is `other`, the counterparty must be identified with either `document` and\n`address`, or `placeOfBirth` and `dateOfBirth`.\n","parameters":[{"description":"ID of the crypto order (deposit or withdrawal) the information refers to.","example":"550e8400-e29b-41d4-a716-446655440030","in":"path","name":"orderId","required":true,"schema":{"format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"exchange-other":{"summary":"Deposit sent from an exchange account of someone else","value":{"address":{"city":"Madrid","countryCode":"ES","street":"Calle Ejemplo 1","zip":"28001"},"document":{"countryCode":"ES","number":"12345678Z","type":"idcard"},"exchangeName":"Binance","name":"John","personType":"person","surname":"Doe","walletOwnership":"other","walletType":"exchange"}},"unhosted-own":{"summary":"Deposit sent from the user's own unhosted wallet","value":{"walletOwnership":"own","walletType":"unhosted"}}},"schema":{"description":"Information about the counterparty of the order and their wallet: who sent the funds of a deposit, or who receives the funds of a withdrawal.\n\nWhen `walletOwnership` is `other`, `personType` and `name` are required, `surname` too unless\n`personType` is `company`, and the counterparty must be identified with either `document` and `address`\nor `placeOfBirth` and `dateOfBirth`.\n","properties":{"address":{"description":"Postal address of the counterparty.","properties":{"city":{"description":"City.","example":"Madrid","type":"string"},"countryCode":{"description":"Country, as an ISO 3166-1 alpha-2 code.","example":"ES","pattern":"^[A-Z]{2}$","type":"string"},"street":{"description":"Street, number and any other address line.","example":"Calle Ejemplo 1","type":"string"},"zip":{"description":"Postal code.","example":"28001","type":"string"}},"required":["countryCode","city","street","zip"],"type":"object"},"dateOfBirth":{"description":"Date of birth of the counterparty, as `YYYY-MM-DD`. It cannot be in the future or more than 100 years ago.","example":"1990-05-17","format":"date","type":"string"},"document":{"description":"Identity document of the counterparty.","properties":{"countryCode":{"description":"Country that issued the document, as an ISO 3166-1 alpha-2 code.","example":"ES","pattern":"^[A-Z]{2}$","type":"string"},"number":{"description":"Number of the document.","example":"12345678Z","type":"string"},"type":{"description":"Kind of document: `idcard` (national ID card), `foreign-id-card` (foreigner ID card),\n`passport`, or `cif` (company tax ID).\n","enum":["cif","foreign-id-card","idcard","passport"],"example":"idcard","type":"string"}},"required":["countryCode","number","type"],"type":"object"},"exchangeName":{"description":"Name of the exchange of the counterparty wallet. Required when `walletType` is `exchange`.","example":"Binance","type":"string"},"name":{"description":"First name of the counterparty, or the company name. Required when `walletOwnership` is `other`.","example":"John","type":"string"},"personType":{"description":"Whether the counterparty is a natural person or a company. Required when `walletOwnership` is `other`.","enum":["person","company"],"example":"person","type":"string"},"placeOfBirth":{"description":"Place of birth of the counterparty.","properties":{"city":{"description":"City of birth.","example":"Madrid","type":"string"},"countryCode":{"description":"Country of birth, as an ISO 3166-1 alpha-2 code.","example":"ES","pattern":"^[A-Z]{2}$","type":"string"}},"required":["countryCode","city"],"type":"object"},"surname":{"description":"Last name of the counterparty. Required when `walletOwnership` is `other`, unless `personType` is `company`.","example":"Doe","type":"string"},"walletOwnership":{"description":"Whether the counterparty wallet belongs to the user (`own`) or to someone else (`other`).","enum":["own","other"],"example":"other","type":"string"},"walletType":{"description":"Whether the counterparty wallet is a hosted exchange wallet or an unhosted (self-custody) wallet.","enum":["exchange","unhosted"],"example":"exchange","type":"string"}},"required":["walletType","walletOwnership"],"type":"object"}}},"required":true},"responses":{"201":{"description":"Travel-rule information accepted. The response has no body."},"400":{"content":{"application/json":{"examples":{"missing-counterparty-data":{"summary":"Someone else's wallet without enough data about the counterparty","value":{"error":"Bad Request","message":"should include more data for other ownership","statusCode":400}},"missing-exchange":{"summary":"Exchange wallet without `exchangeName`","value":{"error":"Bad Request","message":"parameter exchangeName required when walletType is exchange","statusCode":400}},"validation":{"summary":"Invalid value for `walletOwnership`","value":{"error":"Bad Request","message":["walletOwnership must be one of the following values: own, other"],"statusCode":400}}},"schema":{"oneOf":[{"description":"Returned with `400` when the request is rejected field by field rather than against the\npublished contract. It is not the same shape as the contract validation error, and the\ndifference that catches integrators out is that **`message` is an array of strings here**,\nwhile everywhere else it is a single string.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"One human-readable sentence per failed constraint.","example":["iban should not be empty","iban must be a string"],"items":{"type":"string"},"type":"array"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["message","error","statusCode"],"type":"object"},{"description":"Business error returned by the operation.","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Address book 550e8400-e29b-41d4-a716-446655440000 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message"],"type":"object"}]}}},"description":"The body is malformed (`FieldValidationErrorResponse`, with `message` as an array), or\nrequired information is missing for the given `walletType` or `walletOwnership`\n(`BlockchainManagerErrorResponse`, with `message` as a string).\n"},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"example":{"date":"2026-06-01T10:30:00.000Z","errorCode":"B2M_BLOCKCHAIN_MANAGER_TRAVEL_RULE_ORDER_NOT_FOUND","errorType":"GENERIC","message":"Travel rule order not found: 550e8400-e29b-41d4-a716-446655440030"},"schema":{"properties":{"date":{"description":"When the error was produced (ISO 8601)","example":"2025-11-11T11:11:11.111Z","format":"date-time","type":"string"},"errorCode":{"description":"Stable, machine-readable error identifier. Branch on this, never on `message`.","example":"B2M_BLOCKCHAIN_MANAGER_TRAVEL_RULE_ORDER_NOT_FOUND","type":"string"},"errorType":{"enum":["GENERIC"],"type":"string"},"message":{"description":"Human-readable description of the error, intended for logs rather than end users.","example":"Travel rule order not found: 00000000-0000-4000-8000-000000000000","type":"string"},"requestId":{"description":"Identifier of the request that failed. Quote it when reporting an incident.","example":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd","format":"uuid","type":"string"}},"required":["errorCode","message","errorType","date"],"type":"object"}}},"description":"No order with this ID exists for the authenticated user."},"409":{"content":{"application/json":{"example":{"date":"2026-06-01T10:30:00.000Z","errorCode":"B2M_BLOCKCHAIN_MANAGER_INVALID_TRAVEL_RULE_ORDER","errorType":"GENERIC","message":"Invalid Order 550e8400-e29b-41d4-a716-446655440030"},"schema":{"properties":{"date":{"description":"When the error was produced (ISO 8601)","example":"2025-11-11T11:11:11.111Z","format":"date-time","type":"string"},"errorCode":{"description":"Stable, machine-readable error identifier. Branch on this, never on `message`.","example":"B2M_BLOCKCHAIN_MANAGER_TRAVEL_RULE_ORDER_NOT_FOUND","type":"string"},"errorType":{"enum":["GENERIC"],"type":"string"},"message":{"description":"Human-readable description of the error, intended for logs rather than end users.","example":"Travel rule order not found: 00000000-0000-4000-8000-000000000000","type":"string"},"requestId":{"description":"Identifier of the request that failed. Quote it when reporting an incident.","example":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd","format":"uuid","type":"string"}},"required":["errorCode","message","errorType","date"],"type":"object"}}},"description":"The order does not accept travel-rule information in its current state."},"422":{"content":{"application/json":{"example":{"date":"2026-06-01T10:30:00.000Z","errorCode":"B2M_BLOCKCHAIN_MANAGER_UNPROCESSABLE_TRAVEL_RULE_ORDER","errorType":"GENERIC","message":"Unprocessable Travel Rule Order 550e8400-e29b-41d4-a716-446655440030"},"schema":{"properties":{"date":{"description":"When the error was produced (ISO 8601)","example":"2025-11-11T11:11:11.111Z","format":"date-time","type":"string"},"errorCode":{"description":"Stable, machine-readable error identifier. Branch on this, never on `message`.","example":"B2M_BLOCKCHAIN_MANAGER_TRAVEL_RULE_ORDER_NOT_FOUND","type":"string"},"errorType":{"enum":["GENERIC"],"type":"string"},"message":{"description":"Human-readable description of the error, intended for logs rather than end users.","example":"Travel rule order not found: 00000000-0000-4000-8000-000000000000","type":"string"},"requestId":{"description":"Identifier of the request that failed. Quote it when reporting an incident.","example":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd","format":"uuid","type":"string"}},"required":["errorCode","message","errorType","date"],"type":"object"}}},"description":"The travel-rule information could not be registered for the order."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Complete travel rule order","tags":["Blockchain Manager"],"x-product":{"wallet":"Funding"},"x-use":"POST /v2/blockchain-manager/travel-rule-order/{orderId}"}},"/v1/brokerage/draft":{"post":{"description":"Quotes an instant buy or sell and returns a draft you can execute with\n`POST /v1/brokerage/draft/approve`.\n\nCreating a draft moves no funds. It resolves the price, computes fees and runs the same\nchecks the execution will run — funds, limits, pair availability — so a rejection here\nmeans the trade cannot go ahead as requested.\n\n`pair` is written `BASE/QUOTE`. `amount` and `amountCurrencySymbol` fix one side of the\ntrade; see `amountCurrencySymbol` for which one. Omit `paymentMethod` to settle against\nyour wallet balance, or send `source: teller` to charge an external method.\n\nEvery error body has `code` and `description`. Errors raised by the brokerage service also\ncarry `type`, a stable identifier to branch on, and often `data` with the values involved.\nErrors raised by the gateway while reading the request carry neither.\n","requestBody":{"content":{"application/json":{"examples":{"buyFromWallet":{"summary":"Buy BTC spending 50 EUR from the wallet balance","value":{"amount":"50","amountCurrencySymbol":"EUR","operation":"buy","pair":"BTC/EUR"}},"buyWithCard":{"summary":"Buy BTC with a saved card","value":{"amount":"50","amountCurrencySymbol":"EUR","operation":"buy","pair":"BTC/EUR","paymentMethod":{"method":{"params":{"cardId":"3f1c2a9e-7a4b-4d6e-9c1f-2b8e5d7a0c44"},"type":"CREDITCARD"},"source":"teller"}}},"sellBase":{"summary":"Sell 0.001 BTC for EUR","value":{"amount":"0.001","amountCurrencySymbol":"BTC","operation":"sell","pair":"BTC/EUR"}}},"schema":{"properties":{"amount":{"description":"Decimal amount, as a string, expressed in `amountCurrencySymbol`. It is echoed back as\n`denominationAmount`.\n","example":"50","pattern":"^[0-9.]*$","type":"string"},"amountCurrencySymbol":{"description":"Currency `amount` is expressed in. It is echoed back as `denominationSymbol` and decides\nwhich side of the trade is fixed:\n\n- A crypto currency must be one of the two currencies of `pair`\n  (`DENOMINATION_CURRENCY_NOT_IN_PAIR` otherwise). The base currency fixes the amount\n  you give when selling and the amount you receive when buying.\n- A fiat currency does not need to be in the pair, but the pair must contain a fiat\n  currency (`DENOMINATION_FIAT_WITH_CRYPTO_PAIR` otherwise). When it is not the quote\n  currency, the amount is converted to it first.\n","example":"EUR","type":"string"},"concept":{"description":"Free text stored with the draft and copied to the resulting order.","type":"string"},"operation":{"description":"Side of the trade. Matched case-insensitively.","enum":["buy","sell"],"example":"buy","type":"string"},"pair":{"description":"Pair to trade, written `BASE/QUOTE`. With `buy` you receive `BASE` and pay in `QUOTE`;\nwith `sell` you give `BASE` and receive `QUOTE`.\n","example":"BTC/EUR","maxLength":255,"pattern":".*\\/.*","type":"string"},"paymentMethod":{"description":"How the trade is funded. When it is omitted, the trade is settled against your wallet\nbalance, the same as `source: wallet`.\n","properties":{"method":{"description":"Teller payment method used to fund a `buy` when `source` is `teller`.","properties":{"params":{"additionalProperties":true,"description":"Method-specific parameters, forwarded to teller as they are. The app sends `cardId` for\n`CREDITCARD`, `paypalId` for a saved `PAYPAL` account and `paymentMethod: pix` for\n`HUB_LATAM`. The other methods send no parameters.\n","example":{"cardId":"3f1c2a9e-7a4b-4d6e-9c1f-2b8e5d7a0c44"},"type":"object"},"type":{"description":"Teller method. When `source` is `teller`, any other value is rejected with `400`\n`INVALID_PAYMENT_METHOD`.\n","enum":["CREDITCARD","GOOGLE_PAY","APPLE_PAY","HUB_LATAM","PAYPAL","BIZUM"],"type":"string"},"walletId":{"description":"Wallet identifier forwarded to the brokerage service with the payment method.","type":"string"}},"type":"object"},"source":{"description":"`wallet` settles against your balance. `teller` charges an external payment method\ndescribed in `method`. Matched case-insensitively; any other value is rejected with\n`400` `invalid payment method source`.\n","enum":["wallet","teller"],"type":"string"}},"required":["source"],"type":"object"},"userCurrencySymbol":{"description":"Currency used to fill `userInfo` in the response, where price, fee and differential are\nrepeated converted to it.\n","example":"EUR","maxLength":3,"type":"string"}},"required":["pair","operation","amount","amountCurrencySymbol"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"examples":{"buyFromWallet":{"summary":"Buy BTC spending 50 EUR from the wallet balance","value":{"createdAt":"2026-01-01T00:00:00Z","denominationAmount":"50","denominationPrice":"1","denominationRatePair":"EUR/EUR","denominationSymbol":"EUR","destinationAmount":"0.00065807","differentialAmount":"0","differentialPercentage":"0","differentialSymbol":"EUR","draftId":"7c2f5f2a-0f7a-4a44-9f0a-2f5d2f6f9a11","feeAmount":"0.5","feePercentage":"0.01","feeSymbol":"EUR","operation":"buy","originAmount":"50","pair":"BTC/EUR","price":"75980","type":"exchange","updatedAt":"2026-01-01T00:00:00Z","userId":"e0445112-8d3c-4400-85d0-105ebce0ee34","userInfo":{"differentialAmount":"0","differentialSymbol":"EUR","feeAmount":"0.5","feeSymbol":"EUR","price":"75980","priceSymbol":"EUR","userCurrencyRate":"1","userCurrencySymbol":"EUR"}}}},"schema":{"description":"Quote for the requested trade. Amounts are decimal strings. Any field whose value is empty\nis omitted from the response.\n","properties":{"concept":{"description":"`concept` sent in the request.","type":"string"},"createdAt":{"description":"When the draft was created.","format":"date-time","type":"string"},"denominationAmount":{"description":"`amount` sent in the request.","type":"string"},"denominationPrice":{"description":"Rate used to convert the denomination currency into the currency you give; `1` when they are the same.","type":"string"},"denominationRatePair":{"description":"Pair behind `denominationPrice`, written `DENOMINATION/ORIGIN`, for example `EUR/EUR`.","type":"string"},"denominationSymbol":{"description":"`amountCurrencySymbol` sent in the request.","type":"string"},"destinationAmount":{"description":"Amount you receive, in the base currency for `buy` and the quote currency for `sell`.","type":"string"},"differentialAmount":{"description":"Price differential applied to the trade, in `differentialSymbol`.","type":"string"},"differentialPercentage":{"description":"Price differential rate, as a fraction.","type":"string"},"differentialSymbol":{"description":"Currency of `differentialAmount`.","type":"string"},"draftId":{"description":"Identifier to send to `POST /v1/brokerage/draft/approve`.","format":"uuid","type":"string"},"feeAmount":{"description":"Trading fee, in `feeSymbol`.","type":"string"},"feePercentage":{"description":"Trading fee rate, as a fraction (`0.01` is 1%).","type":"string"},"feeSymbol":{"description":"Currency of `feeAmount`.","type":"string"},"issuerId":{"description":"Identifier of the issuer that created the draft.","type":"string"},"issuerIntegrator":{"description":"Integrator origin the gateway recorded for the request.","type":"string"},"issuerName":{"description":"Name of the issuer that created the draft.","type":"string"},"operation":{"description":"Side of the trade.","enum":["buy","sell"],"type":"string"},"originAmount":{"description":"Amount you give, in the quote currency for `buy` and the base currency for `sell`.","type":"string"},"pair":{"description":"Pair of the trade, as requested.","type":"string"},"price":{"description":"Price of one unit of the base currency, in the quote currency.","type":"string"},"spaceCenterFeeDiscount":{"description":"Discount on the trading fee from your Space Center benefits. Omitted when no discount applies.","properties":{"discountAmount":{"description":"Amount discounted from the trading fee.","pattern":"^[0-9.]*$","type":"string"},"discountPercentage":{"description":"Rate discounted from the trading fee.","pattern":"^[0-9.]*$","type":"string"},"originalAmount":{"description":"Trading fee before the discount.","pattern":"^[0-9.]*$","type":"string"},"originalPercentage":{"description":"Trading fee rate before the discount.","pattern":"^[0-9.]*$","type":"string"},"symbol":{"description":"Currency of the amounts.","maxLength":10,"type":"string"}},"required":["originalAmount","discountAmount","originalPercentage","discountPercentage","symbol"],"type":"object"},"spaceCenterTellerFeeDiscount":{"description":"Discount on the teller payment fees from your Space Center benefits. Omitted when no discount applies.","properties":{"fixedDiscountAmount":{"description":"Amount discounted from the fixed teller fee.","pattern":"^[0-9.]*$","type":"string"},"fixedOriginalAmount":{"description":"Fixed teller fee before the discount.","pattern":"^[0-9.]*$","type":"string"},"fixedSymbol":{"description":"Currency of the fixed teller fee.","maxLength":10,"type":"string"},"variableDiscountAmount":{"description":"Amount discounted from the variable teller fee.","pattern":"^[0-9.]*$","type":"string"},"variableDiscountPercentage":{"description":"Rate discounted from the variable teller fee.","pattern":"^[0-9.]*$","type":"string"},"variableOriginalAmount":{"description":"Variable teller fee before the discount.","pattern":"^[0-9.]*$","type":"string"},"variableOriginalPercentage":{"description":"Variable teller fee rate before the discount.","pattern":"^[0-9.]*$","type":"string"},"variableSymbol":{"description":"Currency of the variable teller fee.","maxLength":10,"type":"string"}},"type":"object"},"tellerFeeFixedAmount":{"description":"Fixed fee charged by the teller payment method, in `tellerFeeFixedSymbol`.","type":"string"},"tellerFeeFixedSymbol":{"description":"Currency of `tellerFeeFixedAmount`.","type":"string"},"tellerFeeVariableAmount":{"description":"Variable fee charged by the teller payment method, in `tellerFeeVariableSymbol`.","type":"string"},"tellerFeeVariablePercentage":{"description":"Rate behind `tellerFeeVariableAmount`, as a fraction.","type":"string"},"tellerFeeVariableSymbol":{"description":"Currency of `tellerFeeVariableAmount`.","type":"string"},"type":{"description":"How the trade will be executed.","enum":["exchange","execution"],"type":"string"},"updatedAt":{"description":"When the draft was last updated.","format":"date-time","type":"string"},"userId":{"description":"Owner of the draft.","format":"uuid","type":"string"},"userInfo":{"description":"Price, fee and differential repeated in `userCurrencySymbol`, for display. When a value\ncannot be converted it keeps its original currency, which the matching `*Symbol` field\nreflects.\n","properties":{"differentialAmount":{"description":"Price differential, in `differentialSymbol`.","type":"string"},"differentialSymbol":{"description":"Currency of `differentialAmount`.","type":"string"},"feeAmount":{"description":"Trading fee, in `feeSymbol`.","type":"string"},"feeSymbol":{"description":"Currency of `feeAmount`.","type":"string"},"price":{"description":"Trade price, in `priceSymbol`.","type":"string"},"priceSymbol":{"description":"Currency of `price`.","type":"string"},"userCurrencyRate":{"description":"Conversion rate applied to the display currency.","type":"string"},"userCurrencySymbol":{"description":"Display currency.","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Draft created. Send `draftId` to `POST /v1/brokerage/draft/approve` to execute it."},"400":{"content":{"application/json":{"examples":{"invalidOperation":{"summary":"Unknown operation, rejected by the gateway","value":{"code":400,"description":"invalid operation"}},"invalidPairFormat":{"value":{"code":400,"data":{"pair":"BTCEUR"},"description":"invalid currency pair format: BTCEUR","type":"ERROR_CODE_UNSPECIFIED"}},"invalidPaymentMethod":{"value":{"code":400,"data":{"type":"CASH"},"description":"invalid payment method type: CASH","type":"INVALID_PAYMENT_METHOD"}},"sameCurrencies":{"value":{"code":400,"description":"same pair currencies not allowed: EUR/EUR","type":"SAME_PAIR_CURRENCIES"}}},"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The request was rejected.\n\nRaised by the gateway, without `type`:\n- `invalid request body`: the body is not valid JSON or a field has the wrong type.\n- `invalid operation`: `operation` is not `buy` or `sell`.\n- `invalid payment method source`: `paymentMethod.source` is not `wallet` or `teller`.\n\nRaised by the brokerage service, by `type`:\n- `AMOUNT_NOT_PROVIDED`: no amount to size the trade.\n- `DENOMINATION_CURRENCY_NOT_IN_PAIR`: `amountCurrencySymbol` is a crypto currency\n  outside `pair`.\n- `DENOMINATION_FIAT_WITH_CRYPTO_PAIR`: `amountCurrencySymbol` is fiat and `pair` has\n  no fiat currency.\n- `SAME_PAIR_CURRENCIES`: both sides of `pair` are the same currency.\n- `PAIR_NOT_SUPPORTED`: the pair cannot be traded.\n- `SAME_SOURCE_DESTINATION`: source and destination are the same.\n- `INVALID_PATH`: no execution path exists for the pair.\n- `INVALID_PAYMENT_METHOD`: `paymentMethod.method.type` is not a teller method;\n  `data.type` holds the value sent.\n- `BAD_REQUEST`: the wallet service rejected the request.\n- `ERROR_CODE_UNSPECIFIED`: `pair` is not written `BASE/QUOTE` (`data.pair`), or the\n  operation is not valid for an exchange.\n"},"401":{"content":{"application/json":{"examples":{"unauthorized":{"value":{"code":401,"description":"unauthorized","type":"UNAUTHORIZED"}}},"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"`UNAUTHORIZED`: the wallet service refused the operation for this user. This is not a\ncredentials failure; those return `403`.\n"},"403":{"content":{"application/json":{"examples":{"invalidCredentials":{"value":{"code":403,"description":"invalid credentials"}}},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The API key, signature or nonce could not be validated."},"404":{"content":{"application/json":{"examples":{"currencyNotFound":{"value":{"code":404,"data":{"symbol":"XYZ"},"description":"currency not found with symbol: XYZ","type":"CURRENCY_NOT_FOUND"}}},"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"- `CURRENCY_NOT_FOUND`: a currency of the pair or `amountCurrencySymbol` does not exist;\n  `data.symbol` holds it.\n- `RESOURCE_NOT_FOUND`: the wallet service could not find a resource it needed, such as\n  the wallet for a currency.\n"},"406":{"content":{"application/json":{"examples":{"proformaNotAcceptable":{"value":{"code":406,"description":"proforma not acceptable","type":"PROFORMA_NOT_ACCEPTABLE"}}},"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"`PROFORMA_NOT_ACCEPTABLE`: the wallet service would not accept the movement. The\ndescription carries the wallet service's own message when there is one.\n"},"412":{"content":{"application/json":{"examples":{"currencyActionDisabled":{"value":{"code":412,"data":{"operation":"buy","symbol":"XYZ"},"description":"currency action disabled for symbol 'XYZ' and operation 'buy'","type":"CURRENCY_ACTION_DISABLED"}},"notEnoughFunds":{"summary":"Wallet balance lower than the requested amount","value":{"code":412,"data":{"amount":"10.000000000000000000","balance":"0.000547330000000000","currency":"EUR","walletId":"ff72180f-97d1-4b44-9370-e7052581bf1b"},"description":"not enough funds to perform operation","type":"NOT_ENOUGH_FUNDS"}}},"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The trade is well formed but cannot go ahead right now.\n\n- `NOT_ENOUGH_FUNDS`: your balance does not cover the amount; `data` holds `walletId`,\n  `balance`, `currency` and `amount`.\n- `USER_LIMIT_EXCEEDED`: the trade exceeds one of your limits; `data` holds `limit`,\n  `limitType`, `currency`, `used`, `remaining`, `requestedAmount` and `quantity`.\n- `VOLUME_LIMIT_EXCEEDED`: the trade exceeds a platform volume limit; `data` holds\n  `limit`, `limitType`, `currency` and `requestedAmount`.\n- `MAX_VOLUME_EXCEEDED`: the trade exceeds the maximum volume of a single order;\n  `data` holds `currency`, `maxVolume` and `requestedAmount`.\n- `NOT_ENOUGH_ORDER_BOOK`: there is not enough liquidity for the amount; `data` holds\n  `pair`, `currency`, `maxAmount` and `requestedAmount`.\n- `CURRENCY_ACTION_DISABLED`: this operation is disabled for a currency of the pair;\n  `data` holds `symbol` and `operation`.\n- `OPERATION_BLOCKED`: the operation is blocked.\n- `INVALID_ORDER_TYPE`: the resolved order type cannot be used; `data.type` holds it.\n- `FEE_CONFIGURATION_UNAVAILABLE`: no fee configuration exists for the pair;\n  `data.pair` holds it.\n"},"500":{"content":{"application/json":{"examples":{"internalError":{"value":{"code":500,"description":"an unexpected error occurred","type":"INTERNAL_ERROR"}}},"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"`INTERNAL_ERROR`: the brokerage service failed unexpectedly. Retrying later may\nsucceed.\n"},"502":{"content":{"application/json":{"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The brokerage service could not be reached, or it answered with an error the gateway\ndoes not map to an HTTP status. Such errors keep the `type` the service sent, when it\nsent one.\n"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Create a draft order","tags":["Brokerage"],"x-product":{"wallet":"Brokerage"}}},"/v1/brokerage/draft/approve":{"post":{"description":"Executes a draft created with `POST /v1/brokerage/draft` and returns the resulting order.\n\nOnly `draftId` is required. Several checks of the draft call run again, so a draft that\nwas valid when quoted can still be rejected here — for example with `NOT_ENOUGH_FUNDS` if your\nbalance changed, or `PRICE_PROTECTION` if the price moved too far.\n\nA `200` means the order was created, not that it has settled. With teller payments the\norder can be `payment-pending`, and `paymentMethod` carries the payment session to\ncomplete. Follow the order with `GET /v1/brokerage/order/{orderId}` until it reaches its\nfinal status.\n\nError bodies follow the same rules as `POST /v1/brokerage/draft`: `type`, and often\n`data`, are present on errors raised by the brokerage service.\n","requestBody":{"content":{"application/json":{"examples":{"approve":{"value":{"draftId":"7c2f5f2a-0f7a-4a44-9f0a-2f5d2f6f9a11"}}},"schema":{"properties":{"draftId":{"description":"`draftId` returned by `POST /v1/brokerage/draft`.","format":"uuid","type":"string"},"userCurrencySymbol":{"description":"Currency used to fill `userInfo` in the response.","example":"EUR","type":"string"}},"required":["draftId"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"examples":{"walletBuy":{"summary":"Buy settled against the wallet balance","value":{"order":{"createdAt":"2026-01-01T00:00:01Z","denominationAmount":"50","denominationPrice":"1","denominationRatePair":"EUR/EUR","denominationSymbol":"EUR","destinationAmount":"0.00065807","differentialAmount":"0","differentialPercentage":"0","differentialSymbol":"EUR","feeAmount":"0.5","feePercentage":"0.01","feeSymbol":"EUR","operation":"buy","orderId":"2b9d4c61-5e8f-4a7b-9c3d-1e2f3a4b5c6d","originAmount":"50","pair":"BTC/EUR","price":"75980","status":"completed","type":"exchange","updatedAt":"2026-01-01T00:00:02Z","userId":"e0445112-8d3c-4400-85d0-105ebce0ee34"},"userInfo":{"differentialAmount":"0","differentialSymbol":"EUR","feeAmount":"0.5","feeSymbol":"EUR","price":"75980","priceSymbol":"EUR","userCurrencyRate":"1","userCurrencySymbol":"EUR"}}}},"schema":{"properties":{"order":{"description":"Brokerage order. Amounts are decimal strings. Any field whose value is empty is omitted\nfrom the response.\n","properties":{"concept":{"description":"`concept` sent when the draft was created.","type":"string"},"createdAt":{"description":"When the order was created.","format":"date-time","type":"string"},"denominationAmount":{"description":"`amount` sent when the draft was created.","type":"string"},"denominationPrice":{"description":"Rate used to convert the denomination currency into the currency given.","type":"string"},"denominationRatePair":{"description":"Pair behind `denominationPrice`, written `DENOMINATION/ORIGIN`.","type":"string"},"denominationSymbol":{"description":"`amountCurrencySymbol` sent when the draft was created.","type":"string"},"destinationAmount":{"description":"Amount received, in the base currency for `buy` and the quote currency for `sell`.","type":"string"},"differentialAmount":{"description":"Price differential applied, in `differentialSymbol`.","type":"string"},"differentialPercentage":{"description":"Price differential rate, as a fraction.","type":"string"},"differentialSymbol":{"description":"Currency of `differentialAmount`.","type":"string"},"feeAmount":{"description":"Trading fee, in `feeSymbol`.","type":"string"},"feePercentage":{"description":"Trading fee rate, as a fraction.","type":"string"},"feeSymbol":{"description":"Currency of `feeAmount`.","type":"string"},"issuerId":{"description":"Identifier of the issuer that created the order.","type":"string"},"issuerIntegrator":{"description":"Integrator origin recorded for the request.","type":"string"},"issuerName":{"description":"Name of the issuer that created the order.","type":"string"},"operation":{"description":"Side of the trade.","enum":["buy","sell"],"type":"string"},"orderId":{"description":"Order identifier, used by `GET /v1/brokerage/order/{orderId}`.","format":"uuid","type":"string"},"originAmount":{"description":"Amount given, in the quote currency for `buy` and the base currency for `sell`.","type":"string"},"pair":{"description":"Pair traded, written `BASE/QUOTE`.","type":"string"},"price":{"description":"Price of one unit of the base currency, in the quote currency.","type":"string"},"status":{"description":"Current state of the order. `payment-pending` means the teller payment has not been\nconfirmed yet; the order keeps moving after the approval response, so poll this\nendpoint to follow it.\n","enum":["pending","payment-pending","processing","processed","deposit-send","completed","error","payment-rejected","review","refunded","expired"],"type":"string"},"tellerFeeAmount":{"description":"Fee charged by the teller payment method, in `tellerFeeSymbol`.","type":"string"},"tellerFeeSymbol":{"description":"Currency of `tellerFeeAmount`.","type":"string"},"tellerOrderId":{"description":"Teller order that funds the trade. Only present for teller payments.","format":"uuid","type":"string"},"type":{"description":"How the trade is executed.","enum":["exchange","execution"],"type":"string"},"updatedAt":{"description":"When the order was last updated.","format":"date-time","type":"string"},"userId":{"description":"Owner of the order.","format":"uuid","type":"string"}},"required":["orderId","userId","pair","operation","type","status","originAmount","destinationAmount","price","denominationAmount","denominationSymbol","denominationPrice","denominationRatePair"],"type":"object"},"paymentMethod":{"description":"Payment session returned by teller. Omitted when there is none, as with wallet-balance payments.","properties":{"iframeUrl":{"description":"URL of the teller payment page to show to the user.","type":"string"},"token":{"description":"Token of the teller payment session.","type":"string"}},"type":"object"},"userInfo":{"description":"Price, fee and differential repeated in `userCurrencySymbol`, for display. When a value\ncannot be converted it keeps its original currency, which the matching `*Symbol` field\nreflects.\n","properties":{"differentialAmount":{"description":"Price differential, in `differentialSymbol`.","type":"string"},"differentialSymbol":{"description":"Currency of `differentialAmount`.","type":"string"},"feeAmount":{"description":"Trading fee, in `feeSymbol`.","type":"string"},"feeSymbol":{"description":"Currency of `feeAmount`.","type":"string"},"price":{"description":"Trade price, in `priceSymbol`.","type":"string"},"priceSymbol":{"description":"Currency of `price`.","type":"string"},"userCurrencyRate":{"description":"Conversion rate applied to the display currency.","type":"string"},"userCurrencySymbol":{"description":"Display currency.","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Order created from the draft."},"400":{"content":{"application/json":{"examples":{"invalidBody":{"value":{"code":400,"description":"invalid request body"}}},"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The request was rejected.\n\nRaised by the gateway, without `type`:\n- `invalid request body`: the body is not valid JSON or a field has the wrong type.\n\nRaised by the brokerage service, by `type`:\n- `INVALID_AMOUNT`: the amount to move is not valid.\n- `CURRENCY_REQUIRED`: the movement has no currency.\n- `BAD_REQUEST`: the wallet or teller service rejected the request; `data.message`\n  carries its reason when there is one.\n"},"401":{"content":{"application/json":{"examples":{"unauthorized":{"value":{"code":401,"description":"unauthorized","type":"UNAUTHORIZED"}}},"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"`UNAUTHORIZED`: the wallet service refused the operation for this user. This is not a\ncredentials failure; those return `403`.\n"},"403":{"content":{"application/json":{"examples":{"invalidCredentials":{"value":{"code":403,"description":"invalid credentials"}}},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The API key, signature or nonce could not be validated."},"404":{"content":{"application/json":{"examples":{"draftNotFound":{"value":{"code":404,"data":{"draft_id":"7c2f5f2a-0f7a-4a44-9f0a-2f5d2f6f9a11"},"description":"draft not found: 7c2f5f2a-0f7a-4a44-9f0a-2f5d2f6f9a11","type":"DRAFT_NOT_FOUND"}}},"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"- `DRAFT_NOT_FOUND`: no draft with this `draftId` exists; `data.draft_id`\n  holds the value sent.\n- `RESOURCE_NOT_FOUND`: the wallet or teller service could not find a resource it\n  needed.\n"},"412":{"content":{"application/json":{"examples":{"insufficientInstantFunds":{"value":{"code":412,"description":"insufficient funds in instant service","type":"INSUFFICIENT_INSTANT_FUNDS"}},"priceProtection":{"value":{"code":412,"description":"order cancelled due to price protection","type":"PRICE_PROTECTION"}}},"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The order cannot be executed right now.\n\n- `NOT_ENOUGH_FUNDS`: your balance does not cover the amount.\n- `INSUFFICIENT_INSTANT_FUNDS`: the instant service has no funds to serve the trade.\n- `USER_LIMIT_EXCEEDED`: the trade exceeds one of your limits.\n- `CURRENCY_ACTION_DISABLED`: this operation is disabled for a currency of the pair.\n- `PRICE_PROTECTION`: the order was cancelled because the price moved beyond the\n  protection threshold.\n- `PAYMENT_REJECTED`: teller rejected the payment; `data` holds `tellerOrderId` and\n  `status`.\n- `INVALID_CREDIT_CARD`: the card cannot be used; `data` holds `cardId` and\n  `message`.\n- `PRECONDITION_FAILED` and `PRECONDITION_REQUIRED`: teller requires something before\n  the payment can proceed; `data.message` explains it.\n"},"500":{"content":{"application/json":{"examples":{"depositFailed":{"value":{"code":500,"description":"deposit failed","type":"DEPOSIT_FAILED"}}},"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"- `WITHDRAWAL_FAILED`: the funds could not be taken from the origin.\n- `DEPOSIT_FAILED`: the funds could not be credited to the destination.\n- `INTERNAL_ERROR`: the brokerage service failed unexpectedly.\n"},"502":{"content":{"application/json":{"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The brokerage service could not be reached, or it answered with an error the gateway\ndoes not map to an HTTP status. Such errors keep the `type` the service sent, when it\nsent one.\n"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Approve a draft order","tags":["Brokerage"],"x-product":{"wallet":"Brokerage"}}},"/v1/brokerage/order-setting/{key}":{"get":{"description":"Returns a platform-wide brokerage setting. The value is the same for every user.\n\n- `SLIPPAGE_MAX_PERCENTAGE`: maximum price slippage tolerated for an instant order. The\n  app reads it before creating a draft.\n- `MIN_EXECUTION_EUR_LIMIT`: minimum amount of a brokerage order, in EUR.\n\nValues are decimal strings, not numbers.\n","parameters":[{"description":"Setting to read. Case-sensitive.","example":"SLIPPAGE_MAX_PERCENTAGE","in":"path","name":"key","required":true,"schema":{"description":"Order setting identifier. Case-sensitive.","enum":["MIN_EXECUTION_EUR_LIMIT","SLIPPAGE_MAX_PERCENTAGE"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"minExecution":{"value":{"key":"MIN_EXECUTION_EUR_LIMIT","value":"20"}},"slippage":{"value":{"key":"SLIPPAGE_MAX_PERCENTAGE","value":"0.22"}}},"schema":{"properties":{"key":{"description":"Order setting identifier. Case-sensitive.","enum":["MIN_EXECUTION_EUR_LIMIT","SLIPPAGE_MAX_PERCENTAGE"],"type":"string"},"value":{"description":"Setting value, as a decimal string.","type":"string"}},"type":"object"}}},"description":"Setting found."},"400":{"content":{"application/json":{"examples":{"invalidKey":{"value":{"code":400,"description":"invalid order setting key"}},"unknownKey":{"value":{"code":400,"description":"ORDER_SETTING_KEY_UNKNOWN is not allowed"}}},"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"`key` is not one of the documented settings, lowercase included. The internal\nplaceholder `ORDER_SETTING_KEY_UNKNOWN` is rejected with its own description.\n"},"403":{"content":{"application/json":{"examples":{"invalidCredentials":{"value":{"code":403,"description":"invalid credentials"}}},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The API key, signature or nonce could not be validated."},"404":{"content":{"application/json":{"examples":{"notConfigured":{"value":{"code":404,"description":"Order setting with key 'MIN_EXECUTION_EUR_LIMIT' not found"}}},"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The key is valid but the setting has not been configured."},"500":{"content":{"application/json":{"examples":{"internalError":{"value":{"code":500,"description":"an unexpected error occurred"}}},"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The brokerage service failed unexpectedly."},"502":{"content":{"application/json":{"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The brokerage service could not be reached, or answered with an error the gateway does not map."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get order setting","tags":["Brokerage"],"x-product":{"wallet":"Brokerage"}}},"/v1/brokerage/order/{orderId}":{"get":{"description":"Returns one of your brokerage orders, wrapped in an `order` property.\n\nUse it to follow an order after `POST /v1/brokerage/draft/approve` until `status` reaches\nits final value. Orders of other users are reported as not found.\n","parameters":[{"description":"`order.orderId` returned by `POST /v1/brokerage/draft/approve`.","example":"2b9d4c61-5e8f-4a7b-9c3d-1e2f3a4b5c6d","in":"path","name":"orderId","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"completedBuy":{"value":{"order":{"createdAt":"2026-01-01T00:00:01Z","denominationAmount":"50","denominationPrice":"1","denominationRatePair":"EUR/EUR","denominationSymbol":"EUR","destinationAmount":"0.00065807","differentialAmount":"0","differentialPercentage":"0","differentialSymbol":"EUR","feeAmount":"0.5","feePercentage":"0.01","feeSymbol":"EUR","operation":"buy","orderId":"2b9d4c61-5e8f-4a7b-9c3d-1e2f3a4b5c6d","originAmount":"50","pair":"BTC/EUR","price":"75980","status":"completed","type":"exchange","updatedAt":"2026-01-01T00:00:02Z","userId":"e0445112-8d3c-4400-85d0-105ebce0ee34"}}}},"schema":{"properties":{"order":{"description":"Brokerage order. Amounts are decimal strings. Any field whose value is empty is omitted\nfrom the response.\n","properties":{"concept":{"description":"`concept` sent when the draft was created.","type":"string"},"createdAt":{"description":"When the order was created.","format":"date-time","type":"string"},"denominationAmount":{"description":"`amount` sent when the draft was created.","type":"string"},"denominationPrice":{"description":"Rate used to convert the denomination currency into the currency given.","type":"string"},"denominationRatePair":{"description":"Pair behind `denominationPrice`, written `DENOMINATION/ORIGIN`.","type":"string"},"denominationSymbol":{"description":"`amountCurrencySymbol` sent when the draft was created.","type":"string"},"destinationAmount":{"description":"Amount received, in the base currency for `buy` and the quote currency for `sell`.","type":"string"},"differentialAmount":{"description":"Price differential applied, in `differentialSymbol`.","type":"string"},"differentialPercentage":{"description":"Price differential rate, as a fraction.","type":"string"},"differentialSymbol":{"description":"Currency of `differentialAmount`.","type":"string"},"feeAmount":{"description":"Trading fee, in `feeSymbol`.","type":"string"},"feePercentage":{"description":"Trading fee rate, as a fraction.","type":"string"},"feeSymbol":{"description":"Currency of `feeAmount`.","type":"string"},"issuerId":{"description":"Identifier of the issuer that created the order.","type":"string"},"issuerIntegrator":{"description":"Integrator origin recorded for the request.","type":"string"},"issuerName":{"description":"Name of the issuer that created the order.","type":"string"},"operation":{"description":"Side of the trade.","enum":["buy","sell"],"type":"string"},"orderId":{"description":"Order identifier, used by `GET /v1/brokerage/order/{orderId}`.","format":"uuid","type":"string"},"originAmount":{"description":"Amount given, in the quote currency for `buy` and the base currency for `sell`.","type":"string"},"pair":{"description":"Pair traded, written `BASE/QUOTE`.","type":"string"},"price":{"description":"Price of one unit of the base currency, in the quote currency.","type":"string"},"status":{"description":"Current state of the order. `payment-pending` means the teller payment has not been\nconfirmed yet; the order keeps moving after the approval response, so poll this\nendpoint to follow it.\n","enum":["pending","payment-pending","processing","processed","deposit-send","completed","error","payment-rejected","review","refunded","expired"],"type":"string"},"tellerFeeAmount":{"description":"Fee charged by the teller payment method, in `tellerFeeSymbol`.","type":"string"},"tellerFeeSymbol":{"description":"Currency of `tellerFeeAmount`.","type":"string"},"tellerOrderId":{"description":"Teller order that funds the trade. Only present for teller payments.","format":"uuid","type":"string"},"type":{"description":"How the trade is executed.","enum":["exchange","execution"],"type":"string"},"updatedAt":{"description":"When the order was last updated.","format":"date-time","type":"string"},"userId":{"description":"Owner of the order.","format":"uuid","type":"string"}},"required":["orderId","userId","pair","operation","type","status","originAmount","destinationAmount","price","denominationAmount","denominationSymbol","denominationPrice","denominationRatePair"],"type":"object"}},"required":["order"],"type":"object"}}},"description":"Order found."},"403":{"content":{"application/json":{"examples":{"invalidCredentials":{"value":{"code":403,"description":"invalid credentials"}}},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The API key, signature or nonce could not be validated."},"404":{"content":{"application/json":{"examples":{"notAUuid":{"value":{"code":404,"description":"order not found"}},"notFound":{"value":{"code":404,"description":"order with ID 00000000-0000-0000-0000-000000000000 not found"}}},"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"No order with this id exists for you. An `orderId` that is not a UUID is rejected by\nthe gateway with the same status and a shorter description.\n"},"500":{"content":{"application/json":{"examples":{"internalError":{"value":{"code":500,"description":"an unexpected error occurred"}}},"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The brokerage service failed unexpectedly."},"502":{"content":{"application/json":{"schema":{"properties":{"code":{"description":"Error code.","type":"integer"},"data":{"additionalProperties":true,"description":"Optional additional error data.","type":"object"},"description":{"description":"Human-readable error message.","type":"string"},"type":{"description":"Error type identifier.","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The brokerage service could not be reached, or answered with an error the gateway does not map."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get order by ID","tags":["Brokerage"],"x-product":{"wallet":"Brokerage"}}},"/v1/compliance/address-book/{addressBookId}/confirm":{"post":{"description":"Confirms a destination address in the address book without needing the email-based\nconfirmation token. Intended for subaccounts that cannot receive the confirmation email\ndirectly.\n\nThe authenticated user is treated as the address book owner. The operation is\nidempotent: if the entry is already approved the endpoint returns `204` without error.\n\nTOTP is sent via the `x-totp` header; only `gauth` is supported as delivery method.\n","parameters":[{"description":"Address book entry UUID.","in":"path","name":"addressBookId","required":true,"schema":{"format":"uuid","type":"string"}},{"description":"TOTP verification code.","in":"header","name":"x-totp","schema":{"description":"4-6 digit TOTP verification code","example":"123456","pattern":"^[0-9]{4,6}$","type":"string"}},{"description":"TOTP delivery channel. Only `gauth` is supported for subaccounts.","in":"header","name":"x-totp-type","schema":{"enum":["gauth"],"type":"string"}}],"responses":{"204":{"description":"Address book entry confirmed (or was already approved)."},"400":{"content":{"application/json":{"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"Invalid address book identifier or TOTP type."},"403":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Invalid credentials, or the caller is not a subaccount (this endpoint is\nrestricted to subaccount users).\n"},"404":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Address book entry not found for this user."},"420":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"TOTP code is invalid."},"428":{"content":{"application/json":{"example":{"data":{"sfaProcessInitialized":false,"sfaType":"gauth"},"error":"Precondition Required","message":"sfa required","statusCode":428},"schema":{"allOf":[{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"},{"properties":{"data":{"allOf":[{"properties":{"availableChannels":{"description":"Phone OTP channels available for the current user","items":{"enum":["sms","call","whatsapp"],"type":"string"},"type":"array"},"defaultChannel":{"enum":["sms","call","whatsapp"],"type":"string"}},"type":"object"},{"properties":{"retryIntervalSeconds":{"type":"integer"},"sfaProcessInitialized":{"type":"boolean"},"sfaType":{"enum":["gauth","sms","email","call","whatsapp"],"type":"string"}},"type":"object"}]}},"type":"object"}]}}},"description":"TOTP is required. The response includes SFA metadata inside `data`\n(`sfaType`, `sfaProcessInitialized`, `availableChannels`, `retryIntervalSeconds`).\n"},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Confirm an address book entry","tags":["Compliance"],"x-product":{"wallet":"Compliance"}}},"/v1/compliance/blockchain-address-confirmation/wallet-movement/{walletMovementId}":{"get":{"deprecated":true,"description":"**Deprecated** — use the address-book confirmation flow instead\n(`POST /v1/compliance/address-book/{addressBookId}/confirm`).\n\nReturns whether a crypto destination address linked to a wallet movement has been\nverified, along with the address details and verification timestamp.\n","parameters":[{"description":"Wallet movement UUID.","in":"path","name":"walletMovementId","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"address":"0x1234567890abcdef1234567890abcdef12345678","isVerified":false,"memotag":null,"network":"ethereum","verifiedAt":null,"walletMovementId":"7c9e6679-7425-40de-944b-e07fc1f90ae7"},"schema":{"properties":{"address":{"example":"0x1234567890abcdef1234567890abcdef12345678","type":"string"},"isVerified":{"example":false,"type":"boolean"},"memotag":{"example":"memo123","nullable":true,"type":"string"},"network":{"example":"ethereum","type":"string"},"verifiedAt":{"format":"date-time","nullable":true,"type":"string"},"walletMovementId":{"example":"7c9e6679-7425-40de-944b-e07fc1f90ae7","format":"uuid","type":"string"}},"required":["walletMovementId","address","network","isVerified"],"type":"object"}}},"description":"Confirmation status found."},"400":{"content":{"application/json":{"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"Invalid wallet movement identifier."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"No blockchain address confirmation linked to this wallet movement."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Deprecated: get blockchain destination address confirmation status","tags":["Compliance"],"x-product":{"wallet":"Compliance"},"x-use":"POST /v1/compliance/address-book/{addressBookId}/confirm"}},"/v1/compliance/blockchain-address-confirmation/wallet-movement/{walletMovementId}/confirm":{"post":{"deprecated":true,"description":"**Deprecated** — use `POST /v1/compliance/address-book/{addressBookId}/confirm` instead.\n\nConfirms a crypto destination address linked to a wallet movement, for subaccounts that\ncannot receive the email-based confirmation. TOTP is sent via the `x-totp` header; only\n`gauth` is supported.\n","parameters":[{"description":"Wallet movement UUID.","in":"path","name":"walletMovementId","required":true,"schema":{"format":"uuid","type":"string"}},{"description":"TOTP verification code.","in":"header","name":"x-totp","schema":{"description":"4-6 digit TOTP verification code","example":"123456","pattern":"^[0-9]{4,6}$","type":"string"}},{"description":"TOTP delivery channel. Only `gauth` is supported for subaccounts.","in":"header","name":"x-totp-type","schema":{"enum":["gauth"],"type":"string"}}],"responses":{"204":{"description":"Destination address verified."},"400":{"content":{"application/json":{"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"Invalid wallet movement identifier or TOTP type."},"403":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Invalid credentials, or the caller is not a subaccount (this endpoint is\nrestricted to subaccount users).\n"},"404":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"No blockchain address confirmation linked to this wallet movement."},"420":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"TOTP code is invalid."},"428":{"content":{"application/json":{"example":{"data":{"sfaProcessInitialized":false,"sfaType":"gauth"},"error":"Precondition Required","message":"sfa required","statusCode":428},"schema":{"allOf":[{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"},{"properties":{"data":{"allOf":[{"properties":{"availableChannels":{"description":"Phone OTP channels available for the current user","items":{"enum":["sms","call","whatsapp"],"type":"string"},"type":"array"},"defaultChannel":{"enum":["sms","call","whatsapp"],"type":"string"}},"type":"object"},{"properties":{"retryIntervalSeconds":{"type":"integer"},"sfaProcessInitialized":{"type":"boolean"},"sfaType":{"enum":["gauth","sms","email","call","whatsapp"],"type":"string"}},"type":"object"}]}},"type":"object"}]}}},"description":"TOTP is required. The response includes SFA metadata inside `data`.\n"},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Deprecated: confirm blockchain destination address by wallet movement","tags":["Compliance"],"x-product":{"wallet":"Compliance"},"x-use":"POST /v1/compliance/address-book/{addressBookId}/confirm"}},"/v1/currency/catalog":{"get":{"description":"Returns every supported currency symbol mapped to its display name.\n\nThis replaces the deprecated `GET /v1/type`. The response is a flat object whose keys\nare symbols and whose values are names. The crypto catalogue includes testnet symbols\nsuch as `BTCTEST`; use `GET /v2/currency/assets` when you need to tell them apart.\n\n`type` is mandatory. Omitting it fails validation with `400`.\n\nNo authentication is required.\n","parameters":[{"description":"Which symbols to return: `fiat`, `crypto`, or `all` for both merged into one object.\n","example":"crypto","in":"query","name":"type","required":true,"schema":{"enum":["all","fiat","crypto"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"crypto":{"summary":"`type=crypto`, including a testnet symbol","value":{"BTC":"Bitcoin","BTCTEST":"Bitcoin TestNet","ETH":"Ethereum","USDT":"Usdt"}},"fiat":{"summary":"`type=fiat`","value":{"EUR":"Euro","USD":"United States Dollar"}}},"schema":{"additionalProperties":{"type":"string"},"description":"Currency symbols and display names.","type":"object"}}},"description":"Symbol-to-name map for the requested type."},"400":{"content":{"application/json":{"examples":{"missingType":{"summary":"`type` omitted or invalid","value":{"error":"Bad Request","message":["type must be one of the following values: all, fiat, crypto"],"statusCode":400}}},"schema":{"description":"Error body produced by the currency service. `message` is a single string for business errors and an array of strings when the query fails validation. `error` is absent on a bare `404` and on unexpected `500` errors.\n","properties":{"error":{"description":"HTTP reason phrase, such as `Bad Request` or `Not Found`.","type":"string"},"message":{"description":"Error message, or one message per failed validation rule.","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"description":"HTTP status code, repeated in the body.","type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"`type` is missing or is not one of the allowed values."},"500":{"content":{"application/json":{"examples":{"internal":{"value":{"message":"Internal server error","statusCode":500}}},"schema":{"description":"Error body produced by the currency service. `message` is a single string for business errors and an array of strings when the query fails validation. `error` is absent on a bare `404` and on unexpected `500` errors.\n","properties":{"error":{"description":"HTTP reason phrase, such as `Bad Request` or `Not Found`.","type":"string"},"message":{"description":"Error message, or one message per failed validation rule.","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"description":"HTTP status code, repeated in the body.","type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"Unexpected error in the currency service."}},"summary":"List currency symbols","tags":["Currency"],"x-product":{"wallet":"Market"}}},"/v1/currency/convert":{"get":{"deprecated":true,"description":"**Deprecated.** Fetch rates from `GET /v1/currency/rate` or `GET /v1/currency/prices`\nand convert locally instead.\n\nConverts one or more amounts into the `to` currency, each at its own point in time.\n`value` and `time` must have the same number of entries. `from` either has that same\nnumber of entries, or a single symbol that then applies to every amount.\n\nThe result is an array of numbers in request order. A position whose `from` symbol is\nunknown, or for which no rate exists at that time, comes back as `0` rather than as an\nerror, so check for zeros before trusting a result.\n\nNo authentication is required.\n","parameters":[{"description":"Comma-separated source currency symbols, one per amount, or a single symbol used for all amounts. Uppercase only.\n","example":"BTC,ETH","in":"query","name":"from","required":true,"schema":{"pattern":"^[A-Z0-9]{1,10}(,[A-Z0-9]{1,10})*$","type":"string"}},{"description":"Target currency symbol. Exactly one symbol; an unknown symbol, or a comma-separated list, returns `406`.\n","example":"EUR","in":"query","name":"to","required":true,"schema":{"pattern":"^[A-Z0-9]{1,10}$","type":"string"}},{"description":"Comma-separated amounts to convert, in the same order as `time`.","example":"1.5,2.2","in":"query","name":"value","required":true,"schema":{"pattern":"^-?\\d+(?:\\.\\d+)?(?:,-?\\d+(?:\\.\\d+)?)*$","type":"string"}},{"description":"Comma-separated timestamps, one per amount. Each is either an ISO 8601 UTC datetime with milliseconds (`2024-09-24T00:00:00.000Z`) or 13-digit epoch milliseconds.\n","example":"2024-09-24T00:00:00.000Z,1727136000000","in":"query","name":"time","required":true,"schema":{"pattern":"^((([0-9]{4}-[0-9]{1,2}-[0-9]{1,2}T[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}\\.[0-9]{1,3}Z)|([0-9]{13})),?)+$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"btcToEur":{"summary":"One bitcoin converted to euros at a point in time","value":[97672.55871345589]},"unknownSource":{"summary":"Second `from` symbol unknown, so its position is `0`","value":[97672.55871345589,0]}},"schema":{"items":{"type":"number"},"type":"array"}}},"description":"Converted amounts in the same order as the request tuples."},"400":{"content":{"application/json":{"examples":{"lengthMismatch":{"summary":"Different number of values and times","value":{"error":"Bad Request","message":"value, time or from length mismatch","statusCode":400}},"missingParameter":{"summary":"`value` omitted","value":{"error":"Bad Request","message":["value must be a string","value must match /^-?\\d+(?:\\.\\d+)?(?:,-?\\d+(?:\\.\\d+)?)*$/ regular expression","value should not be empty"],"statusCode":400}}},"schema":{"description":"Error body produced by the currency service. `message` is a single string for business errors and an array of strings when the query fails validation. `error` is absent on a bare `404` and on unexpected `500` errors.\n","properties":{"error":{"description":"HTTP reason phrase, such as `Bad Request` or `Not Found`.","type":"string"},"message":{"description":"Error message, or one message per failed validation rule.","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"description":"HTTP status code, repeated in the body.","type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"A parameter is missing or does not match its pattern, or the number of `value`, `time` and `from` entries do not line up.\n"},"406":{"content":{"application/json":{"examples":{"unknownTarget":{"value":{"error":"Not Acceptable","message":"Currency XYZ not acceptable","statusCode":406}}},"schema":{"description":"Error body produced by the currency service. `message` is a single string for business errors and an array of strings when the query fails validation. `error` is absent on a bare `404` and on unexpected `500` errors.\n","properties":{"error":{"description":"HTTP reason phrase, such as `Bad Request` or `Not Found`.","type":"string"},"message":{"description":"Error message, or one message per failed validation rule.","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"description":"HTTP status code, repeated in the body.","type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"The `to` currency is not known to the service."},"500":{"content":{"application/json":{"examples":{"internal":{"value":{"message":"Internal server error","statusCode":500}}},"schema":{"description":"Error body produced by the currency service. `message` is a single string for business errors and an array of strings when the query fails validation. `error` is absent on a bare `404` and on unexpected `500` errors.\n","properties":{"error":{"description":"HTTP reason phrase, such as `Bad Request` or `Not Found`.","type":"string"},"message":{"description":"Error message, or one message per failed validation rule.","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"description":"HTTP status code, repeated in the body.","type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"Unexpected error in the currency service."}},"summary":"Convert amounts using historical rates (deprecated)","tags":["Currency"],"x-product":{"wallet":"Market"},"x-use":"GET /v1/currency/rate"}},"/v1/currency/ohlca/{symbol}":{"get":{"description":"Returns open, high, low, close and average USD prices for one asset over a window that\nends at `time` and spans `timeframe` backwards. With `timeframe=1D` and no `time`, the\nwindow is the last 24 hours.\n\nThe symbol can be a crypto or a fiat currency. All prices are decimal strings in USD,\nderived from the stored rates against the dollar. `average` is the inverse of the mean\nrate over the window, which is a harmonic mean of the price rather than an arithmetic\none. A value of `\"0\"` means the stored rate was zero.\n\n`404` means the service has no rates for that asset inside the window.\n\nNo authentication is required.\n","parameters":[{"description":"Asset symbol, such as `BTC` or `EUR`. Case-sensitive.","example":"BTC","in":"path","name":"symbol","required":true,"schema":{"pattern":"^[A-Z0-9]{1,10}$","type":"string"}},{"description":"Length of the window, counted backwards from `time`.","example":"1D","in":"query","name":"timeframe","required":true,"schema":{"enum":["1H","4H","12H","1D","1W","1M","1Y"],"type":"string"}},{"description":"End of the window, as an ISO 8601 datetime. Defaults to the current time.\n","example":"2024-09-24T00:00:00.000Z","in":"query","name":"time","schema":{"format":"date-time","type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"btcDaily":{"summary":"`timeframe=1D` for BTC","value":{"average":"77577.56473380463","close":"78823.60190245666","high":"78997.7573705082","low":"76739.54602946785","open":"76863.33264249183"}}},"schema":{"properties":{"average":{"description":"Inverse of the mean USD rate over the window.","format":"number","type":"string"},"close":{"description":"USD price at the last rate in the window.","format":"number","type":"string"},"high":{"description":"Highest USD price in the window.","format":"number","type":"string"},"low":{"description":"Lowest USD price in the window.","format":"number","type":"string"},"open":{"description":"USD price at the first rate in the window.","format":"number","type":"string"}},"required":["open","high","low","close","average"],"type":"object"}}},"description":"OHLC and average prices in USD for the requested window."},"400":{"content":{"application/json":{"examples":{"invalidTime":{"summary":"`time` cannot be parsed as a date","value":{"error":"Bad Request","message":["time must be a Date instance"],"statusCode":400}},"invalidTimeframe":{"summary":"`timeframe` missing or not in the enum","value":{"error":"Bad Request","message":["timeframe must be one of the following values: 1H, 4H, 12H, 1D, 1W, 1M, 1Y"],"statusCode":400}},"unknownSymbol":{"summary":"Symbol not known to the service","value":{"error":"Bad Request","message":"invalid currency parameter","statusCode":400}}},"schema":{"description":"Error body produced by the currency service. `message` is a single string for business errors and an array of strings when the query fails validation. `error` is absent on a bare `404` and on unexpected `500` errors.\n","properties":{"error":{"description":"HTTP reason phrase, such as `Bad Request` or `Not Found`.","type":"string"},"message":{"description":"Error message, or one message per failed validation rule.","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"description":"HTTP status code, repeated in the body.","type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"The symbol is not a known currency, `timeframe` is missing or invalid, or `time` is not a valid datetime.\n"},"404":{"content":{"application/json":{"examples":{"noData":{"value":{"message":"Not Found","statusCode":404}}},"schema":{"description":"Error body produced by the currency service. `message` is a single string for business errors and an array of strings when the query fails validation. `error` is absent on a bare `404` and on unexpected `500` errors.\n","properties":{"error":{"description":"HTTP reason phrase, such as `Bad Request` or `Not Found`.","type":"string"},"message":{"description":"Error message, or one message per failed validation rule.","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"description":"HTTP status code, repeated in the body.","type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"No rates are stored for the asset inside the requested window."},"500":{"content":{"application/json":{"examples":{"internal":{"value":{"message":"Internal server error","statusCode":500}}},"schema":{"description":"Error body produced by the currency service. `message` is a single string for business errors and an array of strings when the query fails validation. `error` is absent on a bare `404` and on unexpected `500` errors.\n","properties":{"error":{"description":"HTTP reason phrase, such as `Bad Request` or `Not Found`.","type":"string"},"message":{"description":"Error message, or one message per failed validation rule.","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"description":"HTTP status code, repeated in the body.","type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"Unexpected error in the currency service."}},"summary":"Get OHLC and average price for one asset","tags":["Currency"],"x-product":{"wallet":"Market"}}},"/v1/currency/prices":{"get":{"description":"Returns the current price of every crypto asset in one quote currency, plus the price\none interval ago for each requested interval (for `one_day`, the price 24 hours\nearlier). `time` is the epoch-millisecond timestamp of each point. The service caches\nthese results, so the live quote can be slightly behind the current time.\n\nThe outer key is the asset symbol. Each value is an array whose first entry is always\nthe live quote, without an `interval` field. One entry per requested `interval`\nfollows, in the order the intervals were requested, each carrying its `interval`. Use\nthe pairs to compute price changes over those periods.\n\n`price` is a decimal string: the price of one unit of the asset in `currency`. `\"0\"`\nmeans no price is available for that asset at that point, which is common for testnet\nsymbols.\n\nNo authentication is required.\n","parameters":[{"description":"Quote currency symbol, fiat or crypto (for example `EUR` or `USDT`). Defaults to `USD`.\n","example":"EUR","in":"query","name":"currency","schema":{"pattern":"^[A-Z0-9]{2,10}$","type":"string"}},{"description":"Historical points to add after the live quote. Repeat the parameter (`interval=one_day\u0026interval=one_week`) or pass a comma-separated list (`interval=one_day,one_week`).\n","example":["one_day"],"explode":true,"in":"query","name":"interval","schema":{"items":{"enum":["one_hour","one_day","one_week","one_month","one_year"],"type":"string"},"type":"array"},"style":"form"}],"responses":{"200":{"content":{"application/json":{"examples":{"eurOneDay":{"summary":"`currency=EUR\u0026interval=one_day`","value":{"BTC":[{"price":"67800.19999999999926788638554933","time":1788443700027},{"interval":"one_day","price":"66414.8920197387747352951255467","time":1788356905602}],"ETH":[{"price":"2088.46999999999964471649629925","time":1788443700027},{"interval":"one_day","price":"2070.3587232438828648977352965","time":1788356905602}]}}},"schema":{"additionalProperties":{"items":{"properties":{"interval":{"enum":["one_hour","one_day","one_week","one_month","one_year"],"example":"one_hour","type":"string"},"price":{"example":"58217.00000000000610707973","format":"number","type":"string"},"time":{"example":1738164880677,"format":"int64","type":"integer"}},"required":["time","price"],"type":"object"},"type":"array"},"example":{"BTC":[{"price":"110371.38623354736805754387","time":1756195935883},{"interval":"one_hour","price":"110231.71349246538085289986","time":1756192147095}],"ETH":[{"price":"4440.02673097597063799573","time":1756195935883},{"interval":"one_hour","price":"4440.71349246538085289986","time":1756192147095}]},"type":"object"}}},"description":"Live and historical prices keyed by asset symbol."},"400":{"content":{"application/json":{"examples":{"invalidInterval":{"value":{"error":"Bad Request","message":["each value in interval must be one of the following values: one_hour, one_day, one_week, one_month, one_year"],"statusCode":400}}},"schema":{"description":"Error body produced by the currency service. `message` is a single string for business errors and an array of strings when the query fails validation. `error` is absent on a bare `404` and on unexpected `500` errors.\n","properties":{"error":{"description":"HTTP reason phrase, such as `Bad Request` or `Not Found`.","type":"string"},"message":{"description":"Error message, or one message per failed validation rule.","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"description":"HTTP status code, repeated in the body.","type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"An `interval` value is not in the enum."},"500":{"content":{"application/json":{"examples":{"internal":{"value":{"message":"Internal server error","statusCode":500}}},"schema":{"description":"Error body produced by the currency service. `message` is a single string for business errors and an array of strings when the query fails validation. `error` is absent on a bare `404` and on unexpected `500` errors.\n","properties":{"error":{"description":"HTTP reason phrase, such as `Bad Request` or `Not Found`.","type":"string"},"message":{"description":"Error message, or one message per failed validation rule.","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"description":"HTTP status code, repeated in the body.","type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"Prices for the selected quote currency could not be retrieved."}},"summary":"List asset prices by interval","tags":["Currency"],"x-product":{"wallet":"Market"}}},"/v1/currency/rate":{"get":{"description":"Returns exchange rates against the US dollar for every supported fiat and crypto\nsymbol.\n\nEach rate is how many units of that currency equal one US dollar: `EUR: 0.86` means\n1 USD = 0.86 EUR, and `BTC: 0.0000126` means 1 USD = 0.0000126 BTC. To convert an\namount from A to B, multiply by `rate[B] / rate[A]`.\n\nThe response is an array with one element per requested timestamp, in request order,\nor a single element for the current time when `time` is omitted. Each element has a\n`fiat` map, a `crypto` map, or both, depending on `type`.\n\nNo authentication is required.\n","parameters":[{"description":"`fiat` or `crypto` to return only that map. Omit it, or pass `all`, to receive both.\n","example":"fiat","in":"query","name":"type","schema":{"default":"all","enum":["all","fiat","crypto"],"type":"string"}},{"description":"Comma-separated timestamps, each an ISO 8601 UTC datetime with milliseconds (`2024-09-24T00:00:00.000Z`) or 13-digit epoch milliseconds. Defaults to the current time.\n","example":"2024-09-24T00:00:00.000Z,1727136000000","in":"query","name":"time","schema":{"maxLength":1024,"pattern":"^((([0-9]{4}-[0-9]{1,2}-[0-9]{1,2}T[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}\\.[0-9]{1,3}Z)|([0-9]{13})),?)+$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"current":{"summary":"Current rates, both maps, subset of symbols","value":[{"crypto":{"BTC":0.00001268655549688644,"ETH":0.0004118570053675658},"fiat":{"EUR":0.860151,"USD":1}}]}},"schema":{"items":{"properties":{"crypto":{"additionalProperties":{"type":"number"},"description":"Units of each crypto asset per US dollar. Absent when `type=fiat`.","type":"object"},"fiat":{"additionalProperties":{"type":"number"},"description":"Units of each fiat currency per US dollar. Absent when `type=crypto`.","type":"object"}},"type":"object"},"type":"array"}}},"description":"One element per requested timestamp, each with the rate maps selected by `type`."},"400":{"content":{"application/json":{"examples":{"invalidType":{"value":{"error":"Bad Request","message":["type must be one of the following values: all, fiat, crypto"],"statusCode":400}}},"schema":{"description":"Error body produced by the currency service. `message` is a single string for business errors and an array of strings when the query fails validation. `error` is absent on a bare `404` and on unexpected `500` errors.\n","properties":{"error":{"description":"HTTP reason phrase, such as `Bad Request` or `Not Found`.","type":"string"},"message":{"description":"Error message, or one message per failed validation rule.","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"description":"HTTP status code, repeated in the body.","type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"`type` is not in the enum, or `time` does not match the expected format."},"500":{"content":{"application/json":{"examples":{"internal":{"value":{"message":"Internal server error","statusCode":500}}},"schema":{"description":"Error body produced by the currency service. `message` is a single string for business errors and an array of strings when the query fails validation. `error` is absent on a bare `404` and on unexpected `500` errors.\n","properties":{"error":{"description":"HTTP reason phrase, such as `Bad Request` or `Not Found`.","type":"string"},"message":{"description":"Error message, or one message per failed validation rule.","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"description":"HTTP status code, repeated in the body.","type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"Unexpected error in the currency service."}},"summary":"List USD exchange rates","tags":["Currency"],"x-product":{"wallet":"Market"}}},"/v1/earn/movements":{"post":{"description":"Creates a deposit or withdrawal movement in Earn for the authenticated user.\n\nFor deposits, the amount is transferred from the user's main wallet to the earn wallet.\nFor withdrawals, it is transferred back. An optional `lockPeriodId` can be specified\nto deposit into a locked earn wallet.\n\nReturns the `movementId` and the corresponding `walletMovementId`.\n","requestBody":{"content":{"application/json":{"examples":{"deposit":{"summary":"Deposit BTC into earn","value":{"amount":"0.05","currency":"BTC","type":"deposit"}},"withdrawal":{"summary":"Withdraw ETH from earn","value":{"amount":"1.00","currency":"ETH","type":"withdrawal"}}},"schema":{"properties":{"amount":{"description":"Amount to deposit or withdraw (decimal string).","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"currency":{"description":"Currency code (e.g. `BTC`, `ETH`, `B2M`).","type":"string"},"lockPeriodId":{"description":"Lock period to deposit into. Only for `deposit` type with locked wallets.","format":"uuid","type":"string"},"termsAndConditions":{"description":"Terms and conditions acceptance UUID, if required by the pool.","format":"uuid","nullable":true,"type":"string"},"type":{"description":"Type of movement.","enum":["deposit","withdrawal"],"type":"string"},"withholdingAmount":{"description":"Withholding tax amount, if applicable.","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["currency","amount","type"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"movementId":"550e8400-e29b-41d4-a716-446655440010","walletMovementId":"550e8400-e29b-41d4-a716-446655440020"},"schema":{"properties":{"movementId":{"format":"uuid","type":"string"},"walletMovementId":{"format":"uuid","type":"string"}},"required":["movementId","walletMovementId"],"type":"object"}}},"description":"Movement created."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"412":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Not enough funds, user not eligible for earn, or invalid currency."},"417":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Amount must be greater than zero."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Create earn movement","tags":["Earn"],"x-product":{"wallet":"Earn"}}},"/v1/earn/movements/{type}/summary":{"get":{"deprecated":true,"description":"Retrieves aggregated summaries of earn movements grouped by currency for a specific movement type (deposit, reward, withdrawal, discount-funds, or discount-rewards). Returns totals in the original currency and converted to the user's preferred currency. For reward type, use new endpoint /v1/earn/movements/reward/summary.","parameters":[{"in":"path","name":"type","required":true,"schema":{"enum":["deposit","reward","withdrawal","discount-funds","discount-rewards"],"type":"string"}},{"in":"query","name":"userCurrency","schema":{"type":"string"}},{"in":"query","name":"walletId","schema":{"type":"string"}},{"in":"query","name":"rateMoment","required":true,"schema":{"default":"current","enum":["creation","current"],"type":"string"}},{"in":"query","name":"order","required":true,"schema":{"default":"desc","enum":["desc","asc"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"properties":{"currency":{"type":"string"},"total":{"type":"string"},"totalConverted":{"properties":{"amount":{"type":"number"},"currency":{"type":"string"}},"type":"object"},"type":{"enum":["deposit","withdrawal","reward","discount-funds","discount-rewards"],"type":"string"}},"required":["type","currency","total","totalConverted"],"type":"object"},"type":"array"}}},"description":"Movement summary by type"},"401":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Internal Server Error"},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Error"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get movements summary by type","tags":["Earn"],"x-product":{"wallet":"Earn"},"x-use":"GET /v1/earn/movements/reward/summary"}},"/v1/earn/summary":{"get":{"description":"Returns a summary of the authenticated user's earn balances and total rewards,\nconverted to the requested `userCurrency`.\n","parameters":[{"description":"Fiat currency code for converted values (e.g. `EUR`).","in":"query","name":"userCurrency","schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"currency":"EUR","totalBalance":10700.5,"totalRewards":245.32},"schema":{"properties":{"currency":{"type":"string"},"totalBalance":{"type":"number"},"totalRewards":{"type":"number"}},"required":["currency","totalBalance","totalRewards"],"type":"object"}}},"description":"User earn summary."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"500":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Internal server error."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get earn summary","tags":["Earn"],"x-product":{"wallet":"Earn"}}},"/v1/earn/wallets/rewards/config":{"get":{"description":"Returns the reward currency configuration for all earn wallets of the authenticated\nuser. Each entry shows the wallet's currency and its selected reward currency.\n","responses":{"200":{"content":{"application/json":{"example":[{"createdAt":"2025-01-15T10:00:00Z","currency":"BTC","rewardCurrency":"B2M","updatedAt":"2026-09-20T14:30:00Z","walletId":"550e8400-e29b-41d4-a716-446655440001"},{"createdAt":"2025-03-01T08:00:00Z","currency":"ETH","rewardCurrency":"ETH","updatedAt":"2026-09-20T14:30:00Z","walletId":"550e8400-e29b-41d4-a716-446655440002"}],"schema":{"items":{"properties":{"createdAt":{"format":"date-time","type":"string"},"currency":{"type":"string"},"rewardCurrency":{"type":"string"},"updatedAt":{"format":"date-time","type":"string"},"walletId":{"type":"string"}},"type":"object"},"type":"array"}}},"description":"Reward settings for all user wallets."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get rewards configuration for all wallets","tags":["Earn"],"x-product":{"wallet":"Earn"}}},"/v1/earn/wallets/{walletId}":{"get":{"description":"Get details of a specific earn wallet","parameters":[{"in":"path","name":"walletId","required":true,"schema":{"type":"string"}},{"in":"query","name":"userCurrency","schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"balance":{"type":"string"},"convertedBalance":{"properties":{"currency":{"type":"string"},"value":{"type":"string"}},"type":"object"},"createdAt":{"format":"date-time","type":"string"},"currency":{"type":"string"},"lockPeriod":{"properties":{"lockPeriodId":{"type":"string"},"months":{"type":"integer"}},"required":["lockPeriodId","months"],"type":"object"},"updatedAt":{"format":"date-time","type":"string"},"userId":{"type":"string"},"walletId":{"type":"string"}},"required":["walletId","userId","currency","balance","convertedBalance","createdAt","updatedAt"],"type":"object"}}},"description":"Success"},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Error"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get one earn wallet","tags":["Earn"],"x-product":{"wallet":"Earn"}}},"/v1/earn/wallets/{walletId}/movements":{"get":{"description":"Get movements for a specific earn wallet","parameters":[{"in":"path","name":"walletId","required":true,"schema":{"type":"string"}},{"in":"query","name":"userCurrency","schema":{"type":"string"}},{"in":"query","name":"offset","schema":{"default":0,"minimum":0,"type":"integer"}},{"in":"query","name":"limit","schema":{"default":20,"maximum":100,"minimum":1,"type":"integer"}},{"in":"query","name":"sortBy","schema":{"enum":["createdAt"],"type":"string"}},{"in":"query","name":"sortDirection","schema":{"enum":["ascending","descending"],"type":"string"}},{"in":"query","name":"from","schema":{"format":"date-time","type":"string"}},{"in":"query","name":"to","schema":{"format":"date-time","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"properties":{"amount":{"properties":{"currency":{"type":"string"},"value":{"type":"string"}},"required":["value","currency"],"type":"object"},"convertedAmount":{"properties":{"currency":{"type":"string"},"value":{"type":"string"}},"required":["value","currency"],"type":"object"},"createdAt":{"format":"date-time","type":"string"},"issuer":{"properties":{"id":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"}},"type":"object"},"movementId":{"type":"string"},"netAmount":{"properties":{"currency":{"type":"string"},"value":{"type":"string"}},"required":["value","currency"],"type":"object"},"rate":{"properties":{"amount":{"properties":{"currency":{"type":"string"},"value":{"type":"string"}},"type":"object"},"pair":{"type":"string"}},"type":"object"},"source":{"properties":{"currency":{"type":"string"},"walletId":{"type":"string"}},"required":["walletId","currency"],"type":"object"},"type":{"enum":["deposit","reward","withdrawal","discount-funds","discount-rewards"],"type":"string"},"updatedAt":{"format":"date-time","type":"string"},"userId":{"type":"string"},"walletId":{"type":"string"},"withholdingAmount":{"properties":{"currency":{"type":"string"},"value":{"type":"string"}},"required":["value","currency"],"type":"object"}},"required":["movementId","userId","type","createdAt","walletId","amount","withholdingAmount","netAmount"],"type":"object"},"type":"array"},"total":{"type":"integer"}},"required":["total","data"],"type":"object"}}},"description":"Success"},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Error"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get earn wallet movements","tags":["Earn"],"x-product":{"wallet":"Earn"}}},"/v1/earn/wallets/{walletId}/rewards/config":{"get":{"description":"Returns the reward currency configuration for a specific earn wallet.\n","parameters":[{"description":"Earn wallet UUID.","in":"path","name":"walletId","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"createdAt":{"format":"date-time","type":"string"},"currency":{"type":"string"},"rewardCurrency":{"type":"string"},"updatedAt":{"format":"date-time","type":"string"},"walletId":{"type":"string"}},"type":"object"}}},"description":"Reward settings for the wallet."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Wallet not found."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get reward settings by wallet","tags":["Earn"],"x-product":{"wallet":"Earn"}},"patch":{"description":"Changes the currency in which rewards are paid for a specific earn wallet. The\n`rewardCurrency` must be one of the allowed reward currencies for the wallet's pool.\n","parameters":[{"description":"Earn wallet UUID.","in":"path","name":"walletId","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"rewardCurrency":"B2M"},"schema":{"properties":{"rewardCurrency":{"description":"Currency code to receive rewards in (e.g. `B2M`, `BTC`).","type":"string"}},"required":["rewardCurrency"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"createdAt":"2025-01-15T10:00:00Z","currency":"BTC","rewardCurrency":"B2M","updatedAt":"2026-09-23T15:00:00Z","walletId":"550e8400-e29b-41d4-a716-446655440001"},"schema":{"properties":{"createdAt":{"format":"date-time","type":"string"},"currency":{"type":"string"},"rewardCurrency":{"type":"string"},"updatedAt":{"format":"date-time","type":"string"},"walletId":{"type":"string"}},"type":"object"}}},"description":"Updated reward configuration."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Wallet not found."},"406":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Reward currency is not allowed for this pool."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Update wallet reward currency","tags":["Earn"],"x-product":{"wallet":"Earn"}}},"/v1/earn/wallets/{walletId}/rewards/summary":{"get":{"description":"Returns accumulated rewards and total converted reward for a wallet","parameters":[{"in":"path","name":"walletId","required":true,"schema":{"type":"string"}},{"in":"query","name":"userCurrency","schema":{"default":"EUR","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"accumulatedRewards":{"items":{"properties":{"amount":{"example":"11777.15470258","type":"string"},"currency":{"example":"B2M","type":"string"}},"required":["currency","amount"],"type":"object"},"type":"array"},"totalConvertedReward":{"properties":{"amount":{"example":"113.50222045","type":"string"},"currency":{"example":"EUR","type":"string"}},"required":["amount","currency"],"type":"object"}},"required":["accumulatedRewards","totalConvertedReward"],"type":"object"}}},"description":"Wallet's rewards summary"},"401":{"description":"Unauthorized"},"404":{"description":"Wallet not found"},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Error"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get wallet's rewards summary","tags":["Earn"],"x-product":{"wallet":"Earn"}}},"/v1/loan/ltv":{"get":{"description":"Returns the missing amount so a new loan would open at the creation LTV (`0.50`). Send exactly\none of `guaranteeAmount` or `loanAmount`; the other is derived from current prices. Sending\nboth, or neither, is rejected. Also returns both amounts in `userCurrency` and the base APR of\n`loanCurrency` before the user's discounts. `ltv` is a ratio (`0.50` is 50 %). Nothing is\ncreated or reserved.\n\nUse these currencies and amounts to preview the contract with `POST /v1/loan/pre-contract`\n(optional) and to open the loan with `POST /v1/loan/orders`.\n","parameters":[{"description":"Symbol of the currency pledged as guarantee.","example":"BTC","in":"query","name":"guaranteeCurrency","required":true,"schema":{"type":"string"}},{"description":"Guarantee to pledge, in `guaranteeCurrency`. Must be greater than `0`. Send it or\n`loanAmount`, not both.\n","example":"0.05","in":"query","name":"guaranteeAmount","schema":{"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},{"description":"Symbol of the currency to borrow.","example":"USDC","in":"query","name":"loanCurrency","required":true,"schema":{"type":"string"}},{"description":"Amount to borrow, in `loanCurrency`. Must be greater than `0`. Send it or\n`guaranteeAmount`, not both.\n","example":"1625","in":"query","name":"loanAmount","schema":{"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},{"description":"Fiat currency of the converted amounts.","example":"EUR","in":"query","name":"userCurrency","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"fromGuaranteeAmount":{"summary":"Loan calculated from `guaranteeAmount=0.05`","value":{"apr":"0.1500","guaranteeAmount":"0.05","guaranteeAmountConverted":"2990.000000000000000000","guaranteeCurrency":"BTC","loanAmount":"1625.000000000000000000","loanAmountConverted":"1495.000000000000000000","loanCurrency":"USDC","ltv":"0.5000","userCurrency":"EUR"}},"fromLoanAmount":{"summary":"Guarantee calculated from `loanAmount=1625`","value":{"apr":"0.1500","guaranteeAmount":"0.050000000000000000","guaranteeAmountConverted":"2990.000000000000000000","guaranteeCurrency":"BTC","loanAmount":"1625","loanAmountConverted":"1495.000000000000000000","loanCurrency":"USDC","ltv":"0.5000","userCurrency":"EUR"}}},"schema":{"description":"The missing amount so a new loan would open at the creation LTV (`0.50`). Nothing is created\nor reserved.\n","properties":{"apr":{"description":"Base APR of `loanCurrency`, as a fraction with 4 decimals (`0.1500` is 15 %). The user's\ndiscounts are not applied.\n","example":"0.1500","pattern":"^[0-9]+\\.[0-9]{4}$","type":"string"},"guaranteeAmount":{"description":"Guarantee of the loan, in `guaranteeCurrency`. It echoes `guaranteeAmount` when it was\nsent; otherwise it is calculated, with 18 decimals.\n","example":"0.05","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"guaranteeAmountConverted":{"description":"Value of `guaranteeAmount` in `userCurrency` at current prices.","example":"2990.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"guaranteeCurrency":{"description":"Symbol of the guarantee currency, as requested.","example":"BTC","type":"string"},"loanAmount":{"description":"Loan amount, in `loanCurrency`. It echoes `loanAmount` when it was sent; otherwise it is\ncalculated, with 18 decimals.\n","example":"1625.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"loanAmountConverted":{"description":"Value of `loanAmount` in `userCurrency` at current prices.","example":"1495.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"loanCurrency":{"description":"Symbol of the loan currency, as requested.","example":"USDC","type":"string"},"ltv":{"description":"Loan-to-value of the new loan, as a fraction with 4 decimals. It is `0.5000` except\nfor rounding, because the missing amount is calculated for a 50 % LTV.\n","example":"0.5000","pattern":"^[0-9]+\\.[0-9]{4}$","type":"string"},"userCurrency":{"description":"Fiat currency of the converted amounts, as requested.","example":"EUR","type":"string"}},"required":["guaranteeCurrency","guaranteeAmount","guaranteeAmountConverted","loanCurrency","loanAmount","loanAmountConverted","apr","ltv","userCurrency"],"type":"object"}}},"description":"The amounts for a new loan at a 50 % LTV."},"400":{"content":{"application/json":{"example":{"error":"Bad Request","message":["userCurrency must be a string"],"statusCode":400},"schema":{"description":"Returned with `400` when the request is rejected field by field rather than against the\npublished contract. It is not the same shape as the contract validation error, and the\ndifference that catches integrators out is that **`message` is an array of strings here**,\nwhile everywhere else it is a single string.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"One human-readable sentence per failed constraint.","example":["iban should not be empty","iban must be a string"],"items":{"type":"string"},"type":"array"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["message","error","statusCode"],"type":"object"}}},"description":"A query parameter is not valid; `message` lists every failed constraint."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The JWT or the API key (with its signature and nonce) could not be validated."},"404":{"content":{"application/json":{"examples":{"cryptoCurrency":{"summary":"Unknown guarantee or loan currency","value":{"error":"Not Found","message":"XYZ not found in crypto rates","statusCode":404}},"fiatCurrency":{"summary":"Unknown user currency","value":{"error":"Not Found","message":"XYZ not found in fiat rates","statusCode":404}}},"schema":{"description":"Error returned by the loan endpoints. Unlike the field validation error, `message` is a single\nstring; it is meant for logs, so branch on the HTTP status rather than on its text.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong.","example":"OrderId 7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message","error"],"type":"object"}}},"description":"There is no price for `guaranteeCurrency`, `loanCurrency` or `userCurrency`."},"412":{"content":{"application/json":{"examples":{"oneAmount":{"summary":"Neither or both amounts sent","value":{"error":"Precondition Failed","message":"there should only be one amount (guaranteeAmount or loanAmount)","statusCode":412}},"zeroAmount":{"summary":"Amount not greater than zero","value":{"date":"2026-10-07T09:12:40.512Z","errorCode":"B2M_LOAN_LTV_ZERO_AMOUNT","errorType":"GENERIC","message":"loan to value amount must be positive","requestId":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd"}}},"schema":{"oneOf":[{"description":"Error returned by the loan endpoints. Unlike the field validation error, `message` is a single\nstring; it is meant for logs, so branch on the HTTP status rather than on its text.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong.","example":"OrderId 7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message","error"],"type":"object"},{"properties":{"date":{"description":"When the error was produced (ISO 8601)","example":"2025-11-11T11:11:11.111Z","format":"date-time","type":"string"},"errorCode":{"description":"Stable, machine-readable error identifier. Branch on this, never on `message`.","example":"B2M_BLOCKCHAIN_MANAGER_TRAVEL_RULE_ORDER_NOT_FOUND","type":"string"},"errorType":{"enum":["GENERIC"],"type":"string"},"message":{"description":"Human-readable description of the error, intended for logs rather than end users.","example":"Travel rule order not found: 00000000-0000-4000-8000-000000000000","type":"string"},"requestId":{"description":"Identifier of the request that failed. Quote it when reporting an incident.","example":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd","format":"uuid","type":"string"}},"required":["errorCode","message","errorType","date"],"type":"object"}]}}},"description":"The amounts cannot be calculated: neither or both of `guaranteeAmount` and `loanAmount` were\nsent, or the amount sent (or its value) is not greater than `0`. Only the second case has\nan `errorCode`.\n"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get the amount required to open a loan at 50% LTV","tags":["Loan"],"x-product":{"wallet":"Loan"}}},"/v1/loan/movements":{"get":{"description":"Returns the movements of the authenticated user's loan orders, newest first. Only `completed`\nmovements are listed. Amounts are converted to EUR at the prices of each movement.\n\nFilter by `orderId` to get the history of one order, and by `type` to get one kind of\nmovement. Page through the results with `limit` and `offset`; `total` is the number of\nmovements matching the filters.\n\n`payload` depends on `type`. Each example of the 200 response is one movement of a different type.\n","parameters":[{"description":"Return only the movements of this loan order.","example":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","in":"query","name":"orderId","schema":{"format":"uuid","type":"string"}},{"description":"Maximum number of movements to return.","example":20,"in":"query","name":"limit","schema":{"default":20,"maximum":500,"minimum":1,"type":"integer"}},{"description":"Number of movements to skip, for pagination.","example":0,"in":"query","name":"offset","schema":{"default":0,"minimum":0,"type":"integer"}},{"description":"Return only the movements of this type.","example":"payback","in":"query","name":"type","schema":{"enum":["request","approve","reject","payback","liquidate","guarantee_increase","guarantee_decrease","expire"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"approve":{"summary":"Payload of an `approve` movement","value":{"data":[{"createdAt":"2026-09-07T10:15:31.480Z","guaranteeRate":{"convertedCurrency":"EUR","currency":"BTC","value":"59800.000000000000000000"},"loanRate":{"convertedCurrency":"EUR","currency":"USDC","value":"0.920000000000000000"},"movementId":"9b2e7c14-5a3f-4d68-8e1b-0c4f6a2d9e37","orderId":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","payload":{"guaranteeAmount":{"converted":"2990.000000000000000000","convertedCurrency":"EUR","currency":"BTC","value":"0.050000000000000000"},"loanAmount":{"converted":"1495.000000000000000000","convertedCurrency":"EUR","currency":"USDC","value":"1625.000000000000000000"},"ltv":"0.5000","previousLtv":"0.5000"},"status":"completed","type":"approve","updatedAt":"2026-09-07T10:15:33.025Z","userId":"5a235979-dbfe-4830-8dbd-c85548bcfcf4"}],"total":1}},"expire":{"summary":"Payload of an `expire` movement","value":{"data":[{"createdAt":"2026-09-10T10:15:30.120Z","guaranteeRate":{"convertedCurrency":"EUR","currency":"BTC","value":"59800.000000000000000000"},"loanRate":{"convertedCurrency":"EUR","currency":"USDC","value":"0.920000000000000000"},"movementId":"2a7d9b31-5e4c-4f02-9d8b-3c6f0e1a5b22","orderId":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","payload":{"isPromotional":false,"loanAmount":{"converted":"1495.000000000000000000","convertedCurrency":"EUR","currency":"USDC","value":"1625.000000000000000000"}},"status":"completed","type":"expire","updatedAt":"2026-09-10T10:15:30.120Z","userId":"5a235979-dbfe-4830-8dbd-c85548bcfcf4"}],"total":1}},"guaranteeDecrease":{"summary":"Payload of a `guarantee_decrease` movement","value":{"data":[{"createdAt":"2026-09-21T08:00:00.000Z","guaranteeRate":{"convertedCurrency":"EUR","currency":"BTC","value":"59800.000000000000000000"},"loanRate":{"convertedCurrency":"EUR","currency":"USDC","value":"0.920000000000000000"},"movementId":"6e1b3f75-9270-4346-a12f-70a324e9f666","orderId":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","payload":{"guaranteeAmount":{"converted":"598.000000000000000000","convertedCurrency":"EUR","currency":"BTC","value":"0.010000000000000000"},"ltv":"0.5052","previousLtv":"0.4200"},"status":"completed","type":"guarantee_decrease","updatedAt":"2026-09-21T08:00:01.200Z","userId":"5a235979-dbfe-4830-8dbd-c85548bcfcf4"}],"total":1}},"guaranteeIncrease":{"summary":"Payload of a `guarantee_increase` movement","value":{"data":[{"createdAt":"2026-09-20T08:00:00.000Z","guaranteeRate":{"convertedCurrency":"EUR","currency":"BTC","value":"59800.000000000000000000"},"loanRate":{"convertedCurrency":"EUR","currency":"USDC","value":"0.920000000000000000"},"movementId":"5d0a2e64-816f-4235-b01e-6f9213d8e555","orderId":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","payload":{"guaranteeAmount":{"converted":"598.000000000000000000","convertedCurrency":"EUR","currency":"BTC","value":"0.010000000000000000"},"ltv":"0.4200","previousLtv":"0.5052"},"status":"completed","type":"guarantee_increase","updatedAt":"2026-09-20T08:00:01.200Z","userId":"5a235979-dbfe-4830-8dbd-c85548bcfcf4"}],"total":1}},"liquidate":{"summary":"Payload of a `liquidate` movement","value":{"data":[{"createdAt":"2026-10-07T03:14:02.110Z","guaranteeRate":{"convertedCurrency":"EUR","currency":"BTC","value":"49950.000000000000000000"},"loanRate":{"convertedCurrency":"EUR","currency":"USDC","value":"0.920000000000000000"},"movementId":"7f2c4086-a381-4457-8230-81b435f0a777","orderId":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","payload":{"detectionLtv":"0.8612","detectionLtvDate":"2026-10-07T03:12:44.018Z","detectionPrice":{"converted":"49950.000000000000000000","convertedCurrency":"EUR","currency":"BTC","value":"49950.000000000000000000"},"feeAmountLiquidated":{"converted":"39.960000000000000000","convertedCurrency":"EUR","currency":"BTC","value":"0.000800000000000000"},"guaranteeAmountLiquidated":{"converted":"1998.000000000000000000","convertedCurrency":"EUR","currency":"BTC","value":"0.040000000000000000"},"guaranteeAmountReturned":{"converted":"459.540000000000000000","convertedCurrency":"EUR","currency":"BTC","value":"0.009200000000000000"},"guaranteeLiquidationPrice":"49950.000000000000000000","liquidationFeePercentage":"0.0200","liquidationLtv":"0.8500","liquidationType":"ltv","orderLtv":"0.8612","totalAmountLiquidated":{"converted":"2037.960000000000000000","convertedCurrency":"EUR","currency":"BTC","value":"0.040800000000000000"},"totalLiquidationPercentage":"1"},"status":"completed","type":"liquidate","updatedAt":"2026-10-07T03:14:08.640Z","userId":"5a235979-dbfe-4830-8dbd-c85548bcfcf4"}],"total":1}},"payback":{"summary":"Payload of a `payback` movement","value":{"data":[{"createdAt":"2026-10-07T09:30:05.210Z","guaranteeRate":{"convertedCurrency":"EUR","currency":"BTC","value":"59800.000000000000000000"},"loanRate":{"convertedCurrency":"EUR","currency":"USDC","value":"0.920000000000000000"},"movementId":"3d6f0a52-8c1e-4b7a-9f2d-6e5c4b3a2f10","orderId":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","payload":{"guaranteeAmount":{"converted":"2990.000000000000000000","convertedCurrency":"EUR","currency":"BTC","value":"0.050000000000000000"},"isCompleted":false,"loanCompletedPercentage":"0.304538457366701849","ltv":"0.3513","paybackAmount":{"converted":"460.000000000000000000","convertedCurrency":"EUR","currency":"USDC","value":"500.000000000000000000"},"previousLtv":"0.5052","remainingAmount":{"converted":"1050.482465753424657534","convertedCurrency":"EUR","currency":"USDC","value":"1141.828767123287671233"}},"status":"completed","type":"payback","updatedAt":"2026-10-07T09:30:06.870Z","userId":"5a235979-dbfe-4830-8dbd-c85548bcfcf4"}],"total":1}},"paybackGuarantee":{"summary":"Payload of a `payback_guarantee` movement","value":{"data":[{"createdAt":"2026-10-07T11:30:05.210Z","guaranteeRate":{"convertedCurrency":"EUR","currency":"BTC","value":"59800.000000000000000000"},"loanRate":{"convertedCurrency":"EUR","currency":"USDC","value":"0.920000000000000000"},"movementId":"4c9f1d53-705e-4124-af0d-5e8102c7d444","orderId":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","payload":{"brokerageGuaranteeSellOrderId":"af87f803-8c4e-4250-b731-16c7089fa321","guaranteeAmount":{"converted":"2392.000000000000000000","convertedCurrency":"EUR","currency":"BTC","value":"0.040000000000000000"},"isCompleted":false,"loanCompletedPercentage":"0.304538457366701849","ltv":"0.3513","paybackAmount":{"converted":"460.000000000000000000","convertedCurrency":"EUR","currency":"USDC","value":"500.000000000000000000"},"paybackGuaranteeAmount":{"converted":"598.000000000000000000","convertedCurrency":"EUR","currency":"BTC","value":"0.010000000000000000"},"previousLtv":"0.5052","remainingAmount":{"converted":"1050.482465753424657534","convertedCurrency":"EUR","currency":"USDC","value":"1141.828767123287671233"}},"status":"completed","type":"payback_guarantee","updatedAt":"2026-10-07T11:30:06.870Z","userId":"5a235979-dbfe-4830-8dbd-c85548bcfcf4"}],"total":1}},"reject":{"summary":"Payload of a `reject` movement","value":{"data":[{"createdAt":"2026-09-08T10:15:30.120Z","guaranteeRate":{"convertedCurrency":"EUR","currency":"BTC","value":"59800.000000000000000000"},"loanRate":{"convertedCurrency":"EUR","currency":"USDC","value":"0.920000000000000000"},"movementId":"1f6c8a20-4d3b-4e91-8c7a-2b5e9d0f4a11","orderId":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","payload":{"isPromotional":false,"loanAmount":{"converted":"1495.000000000000000000","convertedCurrency":"EUR","currency":"USDC","value":"1625.000000000000000000"}},"status":"completed","type":"reject","updatedAt":"2026-09-08T10:15:30.120Z","userId":"5a235979-dbfe-4830-8dbd-c85548bcfcf4"}],"total":1}},"request":{"summary":"Payload of a `request` movement","value":{"data":[{"createdAt":"2026-09-07T10:15:30.120Z","guaranteeRate":{"convertedCurrency":"EUR","currency":"BTC","value":"59800.000000000000000000"},"loanRate":{"convertedCurrency":"EUR","currency":"USDC","value":"0.920000000000000000"},"movementId":"e4a81f36-2c7d-4b95-a0e3-7f5d1b8c6a42","orderId":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","payload":{"loanAmount":{"converted":"1495.000000000000000000","convertedCurrency":"EUR","currency":"USDC","value":"1625.000000000000000000"},"ltv":"0.5000"},"status":"completed","type":"request","updatedAt":"2026-09-07T10:15:30.120Z","userId":"5a235979-dbfe-4830-8dbd-c85548bcfcf4"}],"total":1}}},"schema":{"properties":{"data":{"description":"The movements of this page, newest first. At most `limit` items.","items":{"description":"One operation on a loan order, such as its request, its approval, a repayment or a\nliquidation, with the amounts involved and the prices at that moment. The fields inside\n`payload` depend on `type`; each shape is listed below and shown as its own example on\n`GET /v1/loan/movements`.\n","properties":{"createdAt":{"description":"When the movement happened.","example":"2026-10-07T09:30:05.210Z","format":"date-time","type":"string"},"guaranteeRate":{"allOf":[{"description":"Price of one unit of `currency`, expressed in `convertedCurrency`.","properties":{"convertedCurrency":{"description":"Fiat currency of `value`, the requested `userCurrency` or `EUR` by default.","example":"EUR","type":"string"},"currency":{"description":"Symbol of the priced currency.","example":"BTC","type":"string"},"value":{"description":"Price of one unit of `currency`, in `convertedCurrency`.","example":"59800.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["value","currency","convertedCurrency"],"type":"object"}],"description":"Price of one unit of the guarantee currency when the movement happened, in fiat (EUR by default)."},"loanRate":{"allOf":[{"description":"Price of one unit of `currency`, expressed in `convertedCurrency`.","properties":{"convertedCurrency":{"description":"Fiat currency of `value`, the requested `userCurrency` or `EUR` by default.","example":"EUR","type":"string"},"currency":{"description":"Symbol of the priced currency.","example":"BTC","type":"string"},"value":{"description":"Price of one unit of `currency`, in `convertedCurrency`.","example":"59800.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["value","currency","convertedCurrency"],"type":"object"}],"description":"Price of one unit of the loan currency when the movement happened, in fiat (EUR by default)."},"movementId":{"description":"Identifier of the movement.","example":"3d6f0a52-8c1e-4b7a-9f2d-6e5c4b3a2f10","format":"uuid","type":"string"},"orderId":{"description":"Loan order the movement belongs to.","example":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","format":"uuid","type":"string"},"payload":{"allOf":[{"description":"Details of a movement. Its fields depend on the movement `type`:\n\n- `request`: `loanAmount`, `ltv`.\n- `approve`: `loanAmount`, `guaranteeAmount`, `ltv`, `previousLtv`.\n- `reject` and `expire`: `loanAmount`, `isPromotional`.\n- `payback`: `paybackAmount`, `remainingAmount`, `guaranteeAmount`, `ltv`, `previousLtv`,\n  `isCompleted`, `loanCompletedPercentage`.\n- `payback_guarantee`: the same as `payback`, plus `paybackGuaranteeAmount` and\n  `brokerageGuaranteeSellOrderId`.\n- `guarantee_increase` and `guarantee_decrease`: `guaranteeAmount`, `ltv`, `previousLtv`.\n- `liquidate`: `guaranteeAmountLiquidated`, `feeAmountLiquidated`, `totalAmountLiquidated`,\n  `guaranteeAmountReturned`, `liquidationType`, `liquidationLtv`, `orderLtv`,\n  `guaranteeLiquidationPrice`, `liquidationFeePercentage`, `totalLiquidationPercentage` and,\n  when they were recorded, `detectionLtv`, `detectionLtvDate` and `detectionPrice`.\n\nAmounts carry their fiat value (EUR by default) at the prices of the movement. LTVs and percentages are\nfractions (`0.5000` is 50 %).\n","properties":{"brokerageGuaranteeSellOrderId":{"description":"Brokerage order that sold the guarantee for a `payback_guarantee`; its details are\navailable from `GET /v1/brokerage/order/{orderId}`.\n","example":"af87f803-8c4e-4250-b731-16c7089fa321","format":"uuid","type":"string"},"detectionLtv":{"description":"LTV of the order when the liquidation was detected.","example":"0.8612","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"detectionLtvDate":{"description":"When the liquidation was detected.","example":"2026-10-07T03:12:44.018Z","format":"date-time","type":"string"},"detectionPrice":{"allOf":[{"description":"An amount in its own currency, together with its fiat value.","properties":{"converted":{"description":"Value of `value` in `convertedCurrency`, at the prices of the movement.","example":"460.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"convertedCurrency":{"description":"Fiat currency of `converted`, the requested `userCurrency` or `EUR` by default.","example":"EUR","type":"string"},"currency":{"description":"Symbol of the currency of `value`.","example":"USDC","type":"string"},"value":{"description":"Amount, in `currency`.","example":"500.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["value","currency","converted","convertedCurrency"],"type":"object"}],"description":"Price of one unit of the guarantee currency when the liquidation was detected."},"feeAmountLiquidated":{"allOf":[{"description":"An amount in its own currency, together with its fiat value.","properties":{"converted":{"description":"Value of `value` in `convertedCurrency`, at the prices of the movement.","example":"460.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"convertedCurrency":{"description":"Fiat currency of `converted`, the requested `userCurrency` or `EUR` by default.","example":"EUR","type":"string"},"currency":{"description":"Symbol of the currency of `value`.","example":"USDC","type":"string"},"value":{"description":"Amount, in `currency`.","example":"500.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["value","currency","converted","convertedCurrency"],"type":"object"}],"description":"Liquidation fee charged on the guarantee."},"guaranteeAmount":{"allOf":[{"description":"An amount in its own currency, together with its fiat value.","properties":{"converted":{"description":"Value of `value` in `convertedCurrency`, at the prices of the movement.","example":"460.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"convertedCurrency":{"description":"Fiat currency of `converted`, the requested `userCurrency` or `EUR` by default.","example":"EUR","type":"string"},"currency":{"description":"Symbol of the currency of `value`.","example":"USDC","type":"string"},"value":{"description":"Amount, in `currency`.","example":"500.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["value","currency","converted","convertedCurrency"],"type":"object"}],"description":"Guarantee involved, in the guarantee currency. For `guarantee_increase` and\n`guarantee_decrease` it is the amount added or withdrawn; for the other types it is the\nwhole guarantee of the order.\n"},"guaranteeAmountLiquidated":{"allOf":[{"description":"An amount in its own currency, together with its fiat value.","properties":{"converted":{"description":"Value of `value` in `convertedCurrency`, at the prices of the movement.","example":"460.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"convertedCurrency":{"description":"Fiat currency of `converted`, the requested `userCurrency` or `EUR` by default.","example":"EUR","type":"string"},"currency":{"description":"Symbol of the currency of `value`.","example":"USDC","type":"string"},"value":{"description":"Amount, in `currency`.","example":"500.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["value","currency","converted","convertedCurrency"],"type":"object"}],"description":"Guarantee sold to cancel the debt, in the guarantee currency, fee included."},"guaranteeAmountReturned":{"allOf":[{"description":"An amount in its own currency, together with its fiat value.","properties":{"converted":{"description":"Value of `value` in `convertedCurrency`, at the prices of the movement.","example":"460.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"convertedCurrency":{"description":"Fiat currency of `converted`, the requested `userCurrency` or `EUR` by default.","example":"EUR","type":"string"},"currency":{"description":"Symbol of the currency of `value`.","example":"USDC","type":"string"},"value":{"description":"Amount, in `currency`.","example":"500.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["value","currency","converted","convertedCurrency"],"type":"object"}],"description":"Guarantee returned to the user's wallet after the liquidation."},"guaranteeLiquidationPrice":{"description":"Price of one unit of the guarantee currency, in EUR, used in the liquidation.","example":"49950.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"isCompleted":{"description":"Whether this repayment completed the loan.","example":false,"type":"boolean"},"isPromotional":{"description":"Always `false`.","example":false,"type":"boolean"},"liquidationFeePercentage":{"description":"Liquidation fee, exchange fee included, as a fraction (`0.02` is 2 %). It is the current\nsetting, not necessarily the one in force when the liquidation happened.\n","example":"0.02","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"liquidationLtv":{"description":"LTV threshold that triggered the liquidation.","example":"0.8500","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"liquidationType":{"description":"Why the order was liquidated: `ltv` when its LTV reached the liquidation threshold,\n`interest_payment` when an interest payment expired unpaid, `manual` when Bit2Me liquidated\nit.\n","enum":["ltv","interest_payment","manual"],"example":"ltv","type":"string"},"loanAmount":{"allOf":[{"description":"An amount in its own currency, together with its fiat value.","properties":{"converted":{"description":"Value of `value` in `convertedCurrency`, at the prices of the movement.","example":"460.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"convertedCurrency":{"description":"Fiat currency of `converted`, the requested `userCurrency` or `EUR` by default.","example":"EUR","type":"string"},"currency":{"description":"Symbol of the currency of `value`.","example":"USDC","type":"string"},"value":{"description":"Amount, in `currency`.","example":"500.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["value","currency","converted","convertedCurrency"],"type":"object"}],"description":"Loan amount of the order, in the loan currency."},"loanCompletedPercentage":{"description":"Share of `loanAmount` repaid so far, this repayment included, as a fraction (`0.3045` is\n30.45 %).\n","example":"0.304538457366701849","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"ltv":{"description":"LTV of the order right after the movement.","example":"0.3513","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"orderLtv":{"description":"LTV of the order when it was liquidated, with 4 decimals.","example":"0.8612","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"paybackAmount":{"allOf":[{"description":"An amount in its own currency, together with its fiat value.","properties":{"converted":{"description":"Value of `value` in `convertedCurrency`, at the prices of the movement.","example":"460.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"convertedCurrency":{"description":"Fiat currency of `converted`, the requested `userCurrency` or `EUR` by default.","example":"EUR","type":"string"},"currency":{"description":"Symbol of the currency of `value`.","example":"USDC","type":"string"},"value":{"description":"Amount, in `currency`.","example":"500.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["value","currency","converted","convertedCurrency"],"type":"object"}],"description":"Amount repaid by this movement, in the loan currency."},"paybackGuaranteeAmount":{"allOf":[{"description":"An amount in its own currency, together with its fiat value.","properties":{"converted":{"description":"Value of `value` in `convertedCurrency`, at the prices of the movement.","example":"460.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"convertedCurrency":{"description":"Fiat currency of `converted`, the requested `userCurrency` or `EUR` by default.","example":"EUR","type":"string"},"currency":{"description":"Symbol of the currency of `value`.","example":"USDC","type":"string"},"value":{"description":"Amount, in `currency`.","example":"500.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["value","currency","converted","convertedCurrency"],"type":"object"}],"description":"Guarantee sold to make the repayment, for `payback_guarantee`."},"previousLtv":{"description":"LTV of the order right before the movement.","example":"0.5052","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"remainingAmount":{"allOf":[{"description":"An amount in its own currency, together with its fiat value.","properties":{"converted":{"description":"Value of `value` in `convertedCurrency`, at the prices of the movement.","example":"460.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"convertedCurrency":{"description":"Fiat currency of `converted`, the requested `userCurrency` or `EUR` by default.","example":"EUR","type":"string"},"currency":{"description":"Symbol of the currency of `value`.","example":"USDC","type":"string"},"value":{"description":"Amount, in `currency`.","example":"500.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["value","currency","converted","convertedCurrency"],"type":"object"}],"description":"Debt left to repay after this movement, in the loan currency."},"totalAmountLiquidated":{"allOf":[{"description":"An amount in its own currency, together with its fiat value.","properties":{"converted":{"description":"Value of `value` in `convertedCurrency`, at the prices of the movement.","example":"460.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"convertedCurrency":{"description":"Fiat currency of `converted`, the requested `userCurrency` or `EUR` by default.","example":"EUR","type":"string"},"currency":{"description":"Symbol of the currency of `value`.","example":"USDC","type":"string"},"value":{"description":"Amount, in `currency`.","example":"500.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["value","currency","converted","convertedCurrency"],"type":"object"}],"description":"Guarantee taken in the liquidation, `guaranteeAmountLiquidated` plus `feeAmountLiquidated`."},"totalLiquidationPercentage":{"description":"Share of the loan liquidated, as a fraction. Always `1`, because liquidations are total.","example":"1","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"type":"object"}],"description":"Amounts and LTVs of the movement. Which fields are present depends on `type`:\n\n- `request`: `loanAmount`, `ltv`.\n- `approve`: `loanAmount`, `guaranteeAmount`, `ltv`, `previousLtv`.\n- `reject` and `expire`: `loanAmount`, `isPromotional`.\n- `payback`: `paybackAmount`, `remainingAmount`, `guaranteeAmount`, `ltv`, `previousLtv`,\n  `isCompleted`, `loanCompletedPercentage`.\n- `payback_guarantee`: the same as `payback`, plus `paybackGuaranteeAmount` and\n  `brokerageGuaranteeSellOrderId`.\n- `guarantee_increase` and `guarantee_decrease`: `guaranteeAmount`, `ltv`, `previousLtv`.\n  `guaranteeAmount` is the amount added or withdrawn, not the whole guarantee.\n- `liquidate`: `guaranteeAmountLiquidated`, `feeAmountLiquidated`, `totalAmountLiquidated`,\n  `guaranteeAmountReturned`, `liquidationType`, `liquidationLtv`, `orderLtv`,\n  `guaranteeLiquidationPrice`, `liquidationFeePercentage`, `totalLiquidationPercentage` and,\n  when they were recorded, `detectionLtv`, `detectionLtvDate` and `detectionPrice`.\n"},"status":{"description":"Progress of the movement. `completed` and `canceled` are final; the other values are\nintermediate steps of the funds transfers.\n","enum":["pending","completed","guarantee_received","loan_issued","loan_received","guarantee_returned","guarantee_sold","guarantee_withdrawn","guarantee_swapped","canceled"],"example":"completed","type":"string"},"type":{"description":"What the movement did:\n\n- `request`: the loan was requested.\n- `approve`: the loan was approved and issued.\n- `reject`: the loan was rejected.\n- `expire`: the loan request expired before being approved.\n- `payback`: part or all of the debt was repaid.\n- `payback_guarantee`: debt repaid by selling part of the guarantee.\n- `guarantee_increase`: guarantee was added.\n- `guarantee_decrease`: guarantee was withdrawn.\n- `liquidate`: the guarantee was sold to cancel the debt.\n- `loan_currency_migration`: the loan was moved to another loan currency by Bit2Me.\n","enum":["request","approve","reject","payback","liquidate","guarantee_increase","guarantee_decrease","expire","payback_guarantee","loan_currency_migration"],"example":"guarantee_increase","type":"string"},"updatedAt":{"description":"When the movement last changed status.","example":"2026-10-07T09:30:06.870Z","format":"date-time","type":"string"},"userId":{"description":"Owner of the order, that is, the authenticated user.","example":"5a235979-dbfe-4830-8dbd-c85548bcfcf4","format":"uuid","type":"string"}},"required":["movementId","orderId","userId","type","createdAt","updatedAt","payload","status","loanRate","guaranteeRate"],"type":"object"},"maxItems":500,"type":"array"},"total":{"description":"Number of movements matching the filters, across all pages.","example":3,"minimum":0,"type":"integer"}},"required":["total","data"],"type":"object"}}},"description":"One page of movements."},"400":{"content":{"application/json":{"example":{"error":"Bad Request","message":["limit must not be greater than 500","orderId must be a UUID"],"statusCode":400},"schema":{"description":"Returned with `400` when the request is rejected field by field rather than against the\npublished contract. It is not the same shape as the contract validation error, and the\ndifference that catches integrators out is that **`message` is an array of strings here**,\nwhile everywhere else it is a single string.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"One human-readable sentence per failed constraint.","example":["iban should not be empty","iban must be a string"],"items":{"type":"string"},"type":"array"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["message","error","statusCode"],"type":"object"}}},"description":"A query parameter is not valid; `message` lists every failed constraint."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The JWT or the API key (with its signature and nonce) could not be validated."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"List loan movements","tags":["Loan"],"x-product":{"wallet":"Loan"}}},"/v1/loan/orders":{"get":{"description":"Returns the authenticated user's loan orders, newest first, with their values in EUR at\ncurrent prices, what is left to repay and the state of their interest payments.\n\nFilter by `status` and page through the results with `limit` and `offset`; `total` is the\nnumber of orders matching the filters.\n","parameters":[{"description":"Maximum number of orders to return.","example":20,"in":"query","name":"limit","schema":{"default":250,"maximum":500,"minimum":1,"type":"integer"}},{"description":"Number of orders to skip, for pagination.","example":0,"in":"query","name":"offset","schema":{"default":0,"minimum":0,"type":"integer"}},{"description":"Return only the orders in these statuses. Repeat the parameter for several statuses\n(`status=active\u0026status=pending`); comma-separated values are not supported.\n","example":["active"],"explode":true,"in":"query","name":"status","schema":{"items":{"enum":["pending","active","rejected","completed","liquidated","expired","pending-liquidation"],"type":"string"},"type":"array"},"style":"form"}],"responses":{"200":{"content":{"application/json":{"example":{"data":[{"apr":"0.1500","aprDetails":{"aprDiscounts":[{"discountAmount":"0.0100","type":"recurring-interest-payment"},{"discountAmount":"0.0140","type":"user-level"}],"baseApr":"0.1500","finalApr":"0.1260","interestPaymentDiscount":"0.0100","isCustomUserLevel":false,"totalDiscount":"0.0240","userDiscount":"0.0140"},"createdAt":"2026-09-07T10:15:30.120Z","discount":"0.0140","expiresAt":"2026-09-10T10:15:30.118Z","finishedAt":null,"guaranteeAmount":"0.050000000000000000","guaranteeAmountConverted":"2990.000000000000000000","guaranteeCurrency":"BTC","guaranteeOriginalAmount":"0.050000000000000000","hasActiveAprPromotion":false,"hasRecurringInterestPayment":true,"interestAmount":"16.828767123287671233","interestPayment":{"hasExpiredPayments":false,"hasPendingPayments":true,"liquidationRisk":"none","pendingInterestPaymentAmount":"16.828767123287671233"},"isModifiable":false,"isUserApprovalRequired":false,"liquidationPriceReference":"35542.305882352941176471","loanAmount":"1641.828767123287671233","loanAmountConverted":"1510.482465753424657534","loanCurrency":"USDC","loanOriginalAmount":"1625.000000000000000000","ltv":"0.5052","maxLoanAmount":null,"minLoanAmount":null,"orderId":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","paybackAmount":"0.000000000000000000","paybackAmountConverted":"0.000000000000000000","paybackInterestAmount":"0.000000000000000000","paybackPrincipalAmount":"0.000000000000000000","remainingAmount":"1641.828767123287671233","remainingAmountConverted":"1510.482465753424657534","remainingInterestAmount":"16.828767123287671233","remainingPrincipalAmount":"1625.000000000000000000","requestedByUserId":"5a235979-dbfe-4830-8dbd-c85548bcfcf4","startedAt":"2026-09-07T10:15:31.480Z","status":"active","updatedAt":"2026-10-07T00:00:12.345Z","userId":"5a235979-dbfe-4830-8dbd-c85548bcfcf4"}],"total":1},"schema":{"properties":{"data":{"description":"The orders of this page, newest first. At most `limit` items.","items":{"allOf":[{"description":"A loan order. Amounts are decimal strings, usually with 18 decimals, in the currency named by\nthe matching `guaranteeCurrency` or `loanCurrency`; `ltv` and `apr` are fractions with 4\ndecimals (`0.5000` is 50 %).\n","properties":{"apr":{"description":"Annual percentage rate of the loan before discounts, fixed at creation from the\nconfiguration of `loanCurrency`. The user-level, recurring interest payment and promotion\ndiscounts are subtracted from it when interest accrues.\n","example":"0.1500","pattern":"^[0-9]+\\.[0-9]{4}$","type":"string"},"createdAt":{"description":"When the order was requested.","example":"2026-09-07T10:15:30.120Z","format":"date-time","type":"string"},"expiresAt":{"description":"Deadline for a `pending` order to be approved; past it, the order becomes `expired`. It is\nset at creation on every order but only matters while the order is `pending`.\n","example":"2026-09-10T10:15:30.118Z","format":"date-time","nullable":true,"type":"string"},"finishedAt":{"description":"When the order was closed, by completion, rejection, expiration or liquidation. `null`\nwhile it is open.\n","example":"2027-03-12T16:40:21.905Z","format":"date-time","nullable":true,"type":"string"},"guaranteeAmount":{"description":"Guarantee locked now. Guarantee increases add to it; guarantee decreases and liquidations\ntake from it.\n","example":"0.050000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"guaranteeCurrency":{"description":"Symbol of the currency locked as guarantee.","example":"BTC","type":"string"},"guaranteeOriginalAmount":{"description":"Guarantee locked when the order was created. It never changes afterwards.","example":"0.050000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"hasRecurringInterestPayment":{"description":"`true` when the interest is paid every month, which earns the recurring interest payment\ndiscount; `false` when all the interest is paid at the end.\n","example":true,"type":"boolean"},"interestAmount":{"description":"Interest accrued so far, after discounts. It is already included in `loanAmount`.","example":"16.828767123287671233","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"isModifiable":{"description":"Whether the loan amount and the guarantee can still be changed when the user approves a\nloan offered by Bit2Me, within `minLoanAmount` and `maxLoanAmount`. `false` for loans the\nuser requests.\n","example":false,"type":"boolean"},"loanAmount":{"description":"Debt accrued so far: `loanOriginalAmount` plus `interestAmount`. Repayments do not reduce\nit; the debt still to repay is `loanAmount - paybackAmount`.\n","example":"1641.828767123287671233","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"loanCurrency":{"description":"Symbol of the currency lent.","example":"USDC","type":"string"},"loanOriginalAmount":{"description":"Amount lent when the order was created, that is, the principal.","example":"1625.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"ltv":{"description":"Loan-to-value: the debt still to repay divided by the value of `guaranteeAmount`, both at\ncurrent prices. It is recalculated on every operation and periodically as prices move;\nwhen it reaches the `liquidationLtv` of the guarantee currency (see\n`GET /v2/loan/currency/configuration`) the guarantee is sold.\n","example":"0.5052","pattern":"^[0-9]+\\.[0-9]{4}$","type":"string"},"maxLoanAmount":{"description":"Highest loan amount, in `loanCurrency`, accepted when modifying the order on approval.\n`null` when no bound was set; only relevant when `isModifiable` is `true`.\n","example":"2000.000000000000000000","nullable":true,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"minLoanAmount":{"description":"Lowest loan amount, in `loanCurrency`, accepted when modifying the order on approval.\n`null` when no bound was set; only relevant when `isModifiable` is `true`.\n","example":"1000.000000000000000000","nullable":true,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"orderId":{"description":"Identifier of the loan order.","example":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","format":"uuid","type":"string"},"paybackAmount":{"description":"Total repaid so far, `paybackPrincipalAmount` plus `paybackInterestAmount`.","example":"0.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"paybackInterestAmount":{"description":"Part of `paybackAmount` that went to interest. Every repayment pays the accrued interest\nbefore the principal.\n","example":"0.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"paybackPrincipalAmount":{"description":"Part of `paybackAmount` that went to the principal.","example":"0.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"requestedByUserId":{"description":"Who created the order. It equals `userId` for loans the user requested themselves, and\ndiffers for loans Bit2Me offered to the user, which stay `pending` until the user\napproves them (see `isUserApprovalRequired`).\n","example":"5a235979-dbfe-4830-8dbd-c85548bcfcf4","format":"uuid","type":"string"},"startedAt":{"description":"When the order was approved and the loan paid out. `null` until then.","example":"2026-09-07T10:15:31.480Z","format":"date-time","nullable":true,"type":"string"},"status":{"description":"Where the order is in its lifecycle:\n\n- `pending`: created but not active. Loans the user requests are approved at once, so this\n  is mostly seen on loans offered by Bit2Me that wait for the user's approval. It turns\n  `expired` at `expiresAt`.\n- `active`: the loan was paid out and accrues interest.\n- `completed`: fully repaid; the guarantee was returned to the wallet.\n- `pending-liquidation`: the guarantee is being sold, because the LTV reached the\n  liquidation threshold or an interest payment expired.\n- `liquidated`: the liquidation finished.\n- `rejected`: a pending order was rejected.\n- `expired`: a pending order was not approved before `expiresAt`.\n","enum":["pending","active","rejected","completed","liquidated","expired","pending-liquidation"],"example":"active","type":"string"},"updatedAt":{"description":"When the order last changed. Interest accrual and LTV updates move it too, so it is not a\nsign of user activity.\n","example":"2026-10-07T00:00:12.345Z","format":"date-time","type":"string"},"userId":{"description":"The borrower, that is, the authenticated user.","example":"5a235979-dbfe-4830-8dbd-c85548bcfcf4","format":"uuid","type":"string"}},"required":["orderId","createdAt","updatedAt","userId","requestedByUserId","guaranteeCurrency","guaranteeOriginalAmount","guaranteeAmount","loanCurrency","loanOriginalAmount","loanAmount","paybackAmount","ltv","apr","status","paybackPrincipalAmount","paybackInterestAmount","interestAmount","hasRecurringInterestPayment","isModifiable"],"type":"object"},{"properties":{"aprDetails":{"allOf":[{"description":"How the APR of a loan is built: `finalApr = baseApr - totalDiscount`, where `totalDiscount`\nadds up the reductions listed in `aprDiscounts`. All rates are fractions with 4 decimals\n(`0.1500` is 15 %).\n","properties":{"aprDiscounts":{"description":"Reductions applied, in the order they are applied: recurring interest payment, user level,\nthen promotion. A promotion that overrides all discounts is the only entry. Empty when no\nreduction applies.\n","items":{"description":"One reduction applied to the APR.","properties":{"discountAmount":{"description":"APR points removed by this reduction, as a fraction with 4 decimals (`0.0140` is 1.4\npoints). It is subtracted from the APR, not multiplied by it.\n","example":"0.0140","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"type":{"description":"Origin of the reduction: `recurring-interest-payment` for paying interest monthly,\n`user-level` for the user's Bit2Me level, `promotion` for an APR promotion of the order.\n","enum":["user-level","recurring-interest-payment","promotion"],"example":"user-level","type":"string"}},"required":["type","discountAmount"],"type":"object"},"type":"array"},"baseApr":{"description":"APR before any reduction. For a loan order it is the order's `apr`.","example":"0.1500","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"finalApr":{"description":"APR the loan actually accrues interest at, after every reduction. Never negative.","example":"0.1260","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"interestPaymentDiscount":{"description":"APR points removed from loans that pay interest monthly (`0.0100` is one point). It is the\nconfigured value and is returned even when the loan does not pay interest monthly; whether\nit was applied is shown by a `recurring-interest-payment` entry in `aprDiscounts`.\n","example":"0.0100","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"isCustomUserLevel":{"description":"`true` when the user's level discount was set specifically for them instead of coming from\ntheir Bit2Me level.\n","example":false,"type":"boolean"},"promotion":{"allOf":[{"description":"APR promotion attached to a loan order.","properties":{"discount":{"description":"Configured promotion discount value (0-1 range). Interpretation depends on discountType: when percentage, this fraction of the remaining APR is removed; when absolute, this value is subtracted directly from the remaining APR.\n","example":"0.0500","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"discountAmount":{"description":"Resolved absolute APR reduction after applying the configured discount.\n","example":"0.0014","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"discountType":{"description":"Whether the discount is a percentage of the remaining APR or an absolute APR reduction.\n","enum":["percentage","absolute"],"example":"percentage","type":"string"},"durationDays":{"description":"Promotion duration in days. `null` when the promotion has no fixed duration.","example":30,"nullable":true,"type":"integer"},"endDate":{"description":"When the promotion stops applying. Absent when it has no end date.","example":"2026-10-07T10:15:31.480Z","format":"date-time","type":"string"},"overridesAllDiscounts":{"description":"When true, the promotion overrides all other discounts (user-level and recurring interest payment); when false, it is applied on top of the other discounts.\n","example":false,"type":"boolean"}},"required":["discount","discountType","overridesAllDiscounts","discountAmount"],"type":"object"}],"description":"APR promotion of the loan. Absent when it has none."},"totalDiscount":{"description":"Sum of the reductions in `aprDiscounts`.","example":"0.0240","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"userDiscount":{"description":"APR points removed for the user's level. It is the user's discount rate applied to the APR\nleft after the recurring interest payment discount, so it is an absolute reduction, not a\nrate. `0.0000` when the user has no level discount or a promotion overrides it.\n","example":"0.0140","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["userDiscount","isCustomUserLevel","interestPaymentDiscount","totalDiscount","baseApr","finalApr","aprDiscounts"],"type":"object"}],"description":"How the APR of the order was obtained. When the breakdown is not available, `baseApr`\nand `finalApr` are `apr` and there are no discounts.\n"},"discount":{"description":"The same as `aprDetails.userDiscount`. Present only when it is greater than `0`.","example":"0.0140","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"guaranteeAmountConverted":{"description":"Value of `guaranteeAmount` in EUR.","example":"2990.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"hasActiveAprPromotion":{"description":"Whether an APR promotion is applied to the order.","example":false,"type":"boolean"},"interestPayment":{"description":"State of the monthly interest payments of the loan. When an interest payment goes unpaid, the\nnext one carries the date on which the order will be liquidated. Without interest payments\nevery flag is `false` and the amount is `0`.\n","properties":{"expiredPaymentLiquidationDate":{"description":"When the order will be liquidated unless the pending interest is paid. Present only when\n`hasExpiredPayments` is `true`.\n","example":"2026-11-01T00:00:00.000Z","format":"date-time","type":"string"},"hasExpiredPayments":{"description":"Whether an earlier interest payment went unpaid, so a liquidation date is set.","example":false,"type":"boolean"},"hasPendingPayments":{"description":"Whether the interest payment of the current period is still unpaid.","example":true,"type":"boolean"},"liquidationRisk":{"description":"Risk of liquidation because of unpaid interest:\n\n- `none`: no liquidation date is set.\n- `medium`: the liquidation date falls in a later month.\n- `high`: the liquidation date falls in the current month or has passed.\n","enum":["none","medium","high"],"example":"none","type":"string"},"pendingInterestPaymentAmount":{"description":"Interest pending of payment, in the loan currency. `0` when nothing is pending.","example":"16.828767123287671233","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["hasExpiredPayments","hasPendingPayments","pendingInterestPaymentAmount","liquidationRisk"],"type":"object"},"isUserApprovalRequired":{"description":"Whether the order is a loan offer waiting for the user's approval: it is `pending` and\nwas requested by someone other than the user.\n","example":false,"type":"boolean"},"liquidationPriceReference":{"description":"Price of one unit of the guarantee currency, in EUR, at which the order would reach an\nLTV of `0.85`.\n","example":"35542.305882352941176471","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"loanAmountConverted":{"description":"Value of `loanAmount` in EUR.","example":"1510.482465753424657534","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"paybackAmountConverted":{"description":"Value of `paybackAmount` in EUR.","example":"0.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"remainingAmount":{"description":"Debt left to repay, `loanAmount` minus `paybackAmount`, in the loan currency.","example":"1641.828767123287671233","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"remainingAmountConverted":{"description":"Value of `remainingAmount` in EUR.","example":"1510.482465753424657534","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"remainingInterestAmount":{"description":"Interest left to repay, `interestAmount` minus `paybackInterestAmount`, never below `0`.","example":"16.828767123287671233","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"remainingPrincipalAmount":{"description":"Principal left to repay, `loanOriginalAmount` minus `paybackPrincipalAmount`.","example":"1625.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["remainingAmount","remainingPrincipalAmount","remainingInterestAmount","liquidationPriceReference","loanAmountConverted","guaranteeAmountConverted","paybackAmountConverted","remainingAmountConverted","isUserApprovalRequired","hasActiveAprPromotion","interestPayment","aprDetails"],"type":"object"}],"description":"A loan order with its values in EUR at current prices and what is left to repay. When the order\nis `liquidated`, the remaining amounts are `0`.\n"},"maxItems":500,"type":"array"},"total":{"description":"Number of orders matching the filters, across all pages.","example":1,"minimum":0,"type":"integer"}},"required":["total","data"],"type":"object"}}},"description":"One page of loan orders."},"400":{"content":{"application/json":{"example":{"error":"Bad Request","message":["each value in status must be one of the following values: pending, active, rejected, completed, liquidated, expired, pending-liquidation"],"statusCode":400},"schema":{"description":"Returned with `400` when the request is rejected field by field rather than against the\npublished contract. It is not the same shape as the contract validation error, and the\ndifference that catches integrators out is that **`message` is an array of strings here**,\nwhile everywhere else it is a single string.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"One human-readable sentence per failed constraint.","example":["iban should not be empty","iban must be a string"],"items":{"type":"string"},"type":"array"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["message","error","statusCode"],"type":"object"}}},"description":"A query parameter is not valid; `message` lists every failed constraint."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The JWT or the API key (with its signature and nonce) could not be validated."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"List loan orders","tags":["Loan"],"x-product":{"wallet":"Loan"}},"post":{"description":"Requests a loan for the authenticated user. The guarantee is taken from the user's wallet and\nthe loan is approved and paid into the wallet in the same call, so the order is returned\n`active` together with its `request` and `approve` movements.\n\nGet the amounts first with `GET /v1/loan/ltv`: the order is refused when its LTV goes\ntoo far above the 50 % used for new loans. Optionally, preview the contract first with\n`POST /v1/loan/pre-contract`. The user must be fully verified and have a valid\nresidence address, both currencies must be enabled in `GET /v2/loan/currency/configuration`,\nand `loanAmount` must be at least the `minimumAmount` of the loan currency.\n","requestBody":{"content":{"application/json":{"example":{"guaranteeAmount":"0.05","guaranteeCurrency":"BTC","hasRecurringInterestPayment":true,"loanAmount":"1625","loanCurrency":"USDC","loanPurposeIds":["cd1ce90a-e4a7-4e7e-a34b-37a4edcbbd04"]},"schema":{"description":"The loan to open. Get the missing amount first with `GET /v1/loan/ltv` and send the two amounts\nit returns: the order is rejected when its LTV falls outside the tolerance around 50 %.\nOptionally, preview the contract with `POST /v1/loan/pre-contract`.\n","properties":{"guaranteeAmount":{"description":"Guarantee to lock, in `guaranteeCurrency`. The user's wallet must hold at least this\namount; it is taken from the wallet when the order is approved, which for loans the user\nrequests happens immediately.\n","example":"0.05","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"guaranteeCurrency":{"description":"Symbol of the currency to leave as guarantee. It must be one of the enabled\n`guaranteeCurrencies` of `GET /v2/loan/currency/configuration`.\n","example":"BTC","type":"string"},"hasRecurringInterestPayment":{"default":false,"description":"`true` to pay the interest every month, which lowers the APR by the recurring interest\npayment discount; `false` to pay all the interest at the end, together with the principal.\n","example":false,"type":"boolean"},"loanAmount":{"description":"Amount to borrow, in `loanCurrency`. It must be at least the `minimumAmount` of the loan\ncurrency and fit in the liquidity still available for it. It is paid into the user's\nwallet when the order is approved.\n","example":"1625","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"loanCurrency":{"description":"Symbol of the currency to borrow. It must be one of the enabled `loanCurrencies` of\n`GET /v2/loan/currency/configuration`.\n","example":"USDC","type":"string"},"loanPurposeIds":{"description":"What the user will use the loan for, as identifiers of enabled loan purposes. Optional:\nomit it or send an empty array when the user skips the question. Any unknown or disabled\nidentifier rejects the order with `400`.\n","example":["cd1ce90a-e4a7-4e7e-a34b-37a4edcbbd04"],"items":{"format":"uuid","type":"string"},"type":"array"}},"required":["guaranteeCurrency","guaranteeAmount","loanCurrency","loanAmount"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"example":{"apr":"0.1500","createdAt":"2026-09-07T10:15:30.120Z","createdMovements":[{"movementId":"e4a81f36-2c7d-4b95-a0e3-7f5d1b8c6a42","status":"completed","type":"request"},{"movementId":"9b2e7c14-5a3f-4d68-8e1b-0c4f6a2d9e37","status":"completed","type":"approve"}],"expiresAt":"2026-09-10T10:15:30.118Z","finishedAt":null,"guaranteeAmount":"0.050000000000000000","guaranteeCurrency":"BTC","guaranteeOriginalAmount":"0.050000000000000000","hasRecurringInterestPayment":true,"interestAmount":"0.000000000000000000","isModifiable":false,"loanAmount":"1625.000000000000000000","loanCurrency":"USDC","loanOriginalAmount":"1625.000000000000000000","ltv":"0.5000","maxLoanAmount":null,"minLoanAmount":null,"orderId":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","paybackAmount":"0.000000000000000000","paybackInterestAmount":"0.000000000000000000","paybackPrincipalAmount":"0.000000000000000000","requestedByUserId":"5a235979-dbfe-4830-8dbd-c85548bcfcf4","startedAt":"2026-09-07T10:15:31.480Z","status":"active","updatedAt":"2026-09-07T10:15:31.480Z","userId":"5a235979-dbfe-4830-8dbd-c85548bcfcf4"},"schema":{"allOf":[{"description":"A loan order. Amounts are decimal strings, usually with 18 decimals, in the currency named by\nthe matching `guaranteeCurrency` or `loanCurrency`; `ltv` and `apr` are fractions with 4\ndecimals (`0.5000` is 50 %).\n","properties":{"apr":{"description":"Annual percentage rate of the loan before discounts, fixed at creation from the\nconfiguration of `loanCurrency`. The user-level, recurring interest payment and promotion\ndiscounts are subtracted from it when interest accrues.\n","example":"0.1500","pattern":"^[0-9]+\\.[0-9]{4}$","type":"string"},"createdAt":{"description":"When the order was requested.","example":"2026-09-07T10:15:30.120Z","format":"date-time","type":"string"},"expiresAt":{"description":"Deadline for a `pending` order to be approved; past it, the order becomes `expired`. It is\nset at creation on every order but only matters while the order is `pending`.\n","example":"2026-09-10T10:15:30.118Z","format":"date-time","nullable":true,"type":"string"},"finishedAt":{"description":"When the order was closed, by completion, rejection, expiration or liquidation. `null`\nwhile it is open.\n","example":"2027-03-12T16:40:21.905Z","format":"date-time","nullable":true,"type":"string"},"guaranteeAmount":{"description":"Guarantee locked now. Guarantee increases add to it; guarantee decreases and liquidations\ntake from it.\n","example":"0.050000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"guaranteeCurrency":{"description":"Symbol of the currency locked as guarantee.","example":"BTC","type":"string"},"guaranteeOriginalAmount":{"description":"Guarantee locked when the order was created. It never changes afterwards.","example":"0.050000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"hasRecurringInterestPayment":{"description":"`true` when the interest is paid every month, which earns the recurring interest payment\ndiscount; `false` when all the interest is paid at the end.\n","example":true,"type":"boolean"},"interestAmount":{"description":"Interest accrued so far, after discounts. It is already included in `loanAmount`.","example":"16.828767123287671233","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"isModifiable":{"description":"Whether the loan amount and the guarantee can still be changed when the user approves a\nloan offered by Bit2Me, within `minLoanAmount` and `maxLoanAmount`. `false` for loans the\nuser requests.\n","example":false,"type":"boolean"},"loanAmount":{"description":"Debt accrued so far: `loanOriginalAmount` plus `interestAmount`. Repayments do not reduce\nit; the debt still to repay is `loanAmount - paybackAmount`.\n","example":"1641.828767123287671233","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"loanCurrency":{"description":"Symbol of the currency lent.","example":"USDC","type":"string"},"loanOriginalAmount":{"description":"Amount lent when the order was created, that is, the principal.","example":"1625.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"ltv":{"description":"Loan-to-value: the debt still to repay divided by the value of `guaranteeAmount`, both at\ncurrent prices. It is recalculated on every operation and periodically as prices move;\nwhen it reaches the `liquidationLtv` of the guarantee currency (see\n`GET /v2/loan/currency/configuration`) the guarantee is sold.\n","example":"0.5052","pattern":"^[0-9]+\\.[0-9]{4}$","type":"string"},"maxLoanAmount":{"description":"Highest loan amount, in `loanCurrency`, accepted when modifying the order on approval.\n`null` when no bound was set; only relevant when `isModifiable` is `true`.\n","example":"2000.000000000000000000","nullable":true,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"minLoanAmount":{"description":"Lowest loan amount, in `loanCurrency`, accepted when modifying the order on approval.\n`null` when no bound was set; only relevant when `isModifiable` is `true`.\n","example":"1000.000000000000000000","nullable":true,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"orderId":{"description":"Identifier of the loan order.","example":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","format":"uuid","type":"string"},"paybackAmount":{"description":"Total repaid so far, `paybackPrincipalAmount` plus `paybackInterestAmount`.","example":"0.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"paybackInterestAmount":{"description":"Part of `paybackAmount` that went to interest. Every repayment pays the accrued interest\nbefore the principal.\n","example":"0.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"paybackPrincipalAmount":{"description":"Part of `paybackAmount` that went to the principal.","example":"0.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"requestedByUserId":{"description":"Who created the order. It equals `userId` for loans the user requested themselves, and\ndiffers for loans Bit2Me offered to the user, which stay `pending` until the user\napproves them (see `isUserApprovalRequired`).\n","example":"5a235979-dbfe-4830-8dbd-c85548bcfcf4","format":"uuid","type":"string"},"startedAt":{"description":"When the order was approved and the loan paid out. `null` until then.","example":"2026-09-07T10:15:31.480Z","format":"date-time","nullable":true,"type":"string"},"status":{"description":"Where the order is in its lifecycle:\n\n- `pending`: created but not active. Loans the user requests are approved at once, so this\n  is mostly seen on loans offered by Bit2Me that wait for the user's approval. It turns\n  `expired` at `expiresAt`.\n- `active`: the loan was paid out and accrues interest.\n- `completed`: fully repaid; the guarantee was returned to the wallet.\n- `pending-liquidation`: the guarantee is being sold, because the LTV reached the\n  liquidation threshold or an interest payment expired.\n- `liquidated`: the liquidation finished.\n- `rejected`: a pending order was rejected.\n- `expired`: a pending order was not approved before `expiresAt`.\n","enum":["pending","active","rejected","completed","liquidated","expired","pending-liquidation"],"example":"active","type":"string"},"updatedAt":{"description":"When the order last changed. Interest accrual and LTV updates move it too, so it is not a\nsign of user activity.\n","example":"2026-10-07T00:00:12.345Z","format":"date-time","type":"string"},"userId":{"description":"The borrower, that is, the authenticated user.","example":"5a235979-dbfe-4830-8dbd-c85548bcfcf4","format":"uuid","type":"string"}},"required":["orderId","createdAt","updatedAt","userId","requestedByUserId","guaranteeCurrency","guaranteeOriginalAmount","guaranteeAmount","loanCurrency","loanOriginalAmount","loanAmount","paybackAmount","ltv","apr","status","paybackPrincipalAmount","paybackInterestAmount","interestAmount","hasRecurringInterestPayment","isModifiable"],"type":"object"},{"properties":{"createdMovements":{"description":"Movements created by the operation: `request` and `approve` when an order is created,\n`payback` for a repayment and `guarantee_increase` when guarantee is added. This list is\nonly returned in the response of the operation.\n","items":{"description":"A movement created by the operation.","properties":{"movementId":{"description":"Identifier of the movement.","example":"3d6f0a52-8c1e-4b7a-9f2d-6e5c4b3a2f10","format":"uuid","type":"string"},"status":{"description":"Progress of the movement. `completed` and `canceled` are final; the other values are\nintermediate steps of the funds transfers.\n","enum":["pending","completed","guarantee_received","loan_issued","loan_received","guarantee_returned","guarantee_sold","guarantee_withdrawn","guarantee_swapped","canceled"],"example":"completed","type":"string"},"type":{"description":"What the movement did:\n\n- `request`: the loan was requested.\n- `approve`: the loan was approved and issued.\n- `reject`: the loan was rejected.\n- `expire`: the loan request expired before being approved.\n- `payback`: part or all of the debt was repaid.\n- `payback_guarantee`: debt repaid by selling part of the guarantee.\n- `guarantee_increase`: guarantee was added.\n- `guarantee_decrease`: guarantee was withdrawn.\n- `liquidate`: the guarantee was sold to cancel the debt.\n- `loan_currency_migration`: the loan was moved to another loan currency by Bit2Me.\n","enum":["request","approve","reject","payback","liquidate","guarantee_increase","guarantee_decrease","expire","payback_guarantee","loan_currency_migration"],"example":"guarantee_increase","type":"string"}},"required":["movementId","type","status"],"type":"object"},"type":"array"}},"required":["createdMovements"],"type":"object"}]}}},"description":"The loan was created, approved and paid into the user's wallet."},"400":{"content":{"application/json":{"examples":{"invalidBody":{"summary":"Invalid body","value":{"error":"Bad Request","message":["loanAmount must be a string","each value in loanPurposeIds must be a UUID"],"statusCode":400}},"invalidLoanPurpose":{"summary":"Unknown or disabled loan purpose","value":{"error":"Bad Request","message":"One or more loan purpose IDs are invalid or disabled: 0b6f3c2a-9d84-4e1f-b7a5-3c2e8d1f6a90","statusCode":400}}},"schema":{"oneOf":[{"description":"Returned with `400` when the request is rejected field by field rather than against the\npublished contract. It is not the same shape as the contract validation error, and the\ndifference that catches integrators out is that **`message` is an array of strings here**,\nwhile everywhere else it is a single string.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"One human-readable sentence per failed constraint.","example":["iban should not be empty","iban must be a string"],"items":{"type":"string"},"type":"array"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["message","error","statusCode"],"type":"object"},{"description":"Error returned by the loan endpoints. Unlike the field validation error, `message` is a single\nstring; it is meant for logs, so branch on the HTTP status rather than on its text.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong.","example":"OrderId 7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message","error"],"type":"object"}]}}},"description":"The body is not valid, or a loan purpose is unknown or disabled. Field validation errors\nlist every failed constraint in `message`.\n"},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The JWT or the API key (with its signature and nonce) could not be validated."},"409":{"content":{"application/json":{"example":{"error":"Conflict","message":"not enough funds currently for processing loan amount 1625","statusCode":409},"schema":{"description":"Error returned by the loan endpoints. Unlike the field validation error, `message` is a single\nstring; it is meant for logs, so branch on the HTTP status rather than on its text.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong.","example":"OrderId 7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message","error"],"type":"object"}}},"description":"Bit2Me cannot lend `loanAmount` of the loan currency right now; see `liquidity` in `GET /v2/loan/currency/configuration`."},"412":{"content":{"application/json":{"examples":{"belowMinimum":{"summary":"Loan amount below the minimum","value":{"error":"Precondition Failed","message":"loan amount 20 below minimum: 50.000000000000000000 - Currency: USDC","statusCode":412}},"guaranteeCurrencyNotEnabled":{"summary":"Guarantee currency not enabled","value":{"date":"2026-10-07T09:12:40.512Z","errorCode":"B2M_LOAN_GUARANTEE_CURRENCY_NOT_ENABLED","errorType":"GENERIC","message":"guarantee currency XYZ not enabled","requestId":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd"}},"invalidResidenceCountry":{"summary":"Residence country not allowed","value":{"error":"Precondition Failed","message":"user 5a235979-dbfe-4830-8dbd-c85548bcfcf4 has invalid residence country: XX","statusCode":412}},"loanCurrencyNotEnabled":{"summary":"Loan currency not enabled","value":{"date":"2026-10-07T09:12:40.512Z","errorCode":"B2M_LOAN_LOAN_CURRENCY_NOT_ENABLED","errorType":"GENERIC","message":"loan currency XYZ not enabled","requestId":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd"}},"ltvTooHigh":{"summary":"LTV too high","value":{"error":"Precondition Failed","message":"threshold exceed limits: 0.6000","statusCode":412}},"noResidenceAddress":{"summary":"User without residence address","value":{"error":"Precondition Failed","message":"user 5a235979-dbfe-4830-8dbd-c85548bcfcf4 has no residence address","statusCode":412}},"notEnoughGuarantee":{"summary":"Not enough guarantee in the wallet","value":{"error":"Precondition Failed","message":"not enough user guarantee amount funds for processing 0.020000000000000000 \u003c 0.05","statusCode":412}},"notVerified":{"summary":"User not fully verified","value":{"error":"Precondition Failed","message":"user 5a235979-dbfe-4830-8dbd-c85548bcfcf4 not totally verified - current tier 1","statusCode":412}}},"schema":{"oneOf":[{"description":"Error returned by the loan endpoints. Unlike the field validation error, `message` is a single\nstring; it is meant for logs, so branch on the HTTP status rather than on its text.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong.","example":"OrderId 7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message","error"],"type":"object"},{"properties":{"date":{"description":"When the error was produced (ISO 8601)","example":"2025-11-11T11:11:11.111Z","format":"date-time","type":"string"},"errorCode":{"description":"Stable, machine-readable error identifier. Branch on this, never on `message`.","example":"B2M_BLOCKCHAIN_MANAGER_TRAVEL_RULE_ORDER_NOT_FOUND","type":"string"},"errorType":{"enum":["GENERIC"],"type":"string"},"message":{"description":"Human-readable description of the error, intended for logs rather than end users.","example":"Travel rule order not found: 00000000-0000-4000-8000-000000000000","type":"string"},"requestId":{"description":"Identifier of the request that failed. Quote it when reporting an incident.","example":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd","format":"uuid","type":"string"}},"required":["errorCode","message","errorType","date"],"type":"object"}]}}},"description":"The loan cannot be granted. The causes are:\n\n- The user is not fully verified, has no residence address or lives in a country where\n  loans are not offered.\n- The LTV of the requested amounts is too high.\n- The wallet does not hold `guaranteeAmount`.\n- `loanAmount` is below the minimum of the loan currency.\n- The guarantee or the loan currency is not enabled; only these two causes have an\n  `errorCode`, `B2M_LOAN_GUARANTEE_CURRENCY_NOT_ENABLED` or\n  `B2M_LOAN_LOAN_CURRENCY_NOT_ENABLED`.\n"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Create loan order","tags":["Loan"],"x-product":{"wallet":"Loan"}}},"/v1/loan/orders/{orderId}":{"get":{"description":"Returns one of the authenticated user's loan orders, with its values in EUR at current prices,\nwhat is left to repay and the state of its interest payments.\n","parameters":[{"description":"Identifier of the loan order, a UUID v4.","example":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","in":"path","name":"orderId","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"apr":"0.1500","aprDetails":{"aprDiscounts":[{"discountAmount":"0.0100","type":"recurring-interest-payment"},{"discountAmount":"0.0140","type":"user-level"}],"baseApr":"0.1500","finalApr":"0.1260","interestPaymentDiscount":"0.0100","isCustomUserLevel":false,"totalDiscount":"0.0240","userDiscount":"0.0140"},"createdAt":"2026-09-07T10:15:30.120Z","discount":"0.0140","expiresAt":"2026-09-10T10:15:30.118Z","finishedAt":null,"guaranteeAmount":"0.050000000000000000","guaranteeAmountConverted":"2990.000000000000000000","guaranteeCurrency":"BTC","guaranteeOriginalAmount":"0.050000000000000000","hasActiveAprPromotion":false,"hasRecurringInterestPayment":true,"interestAmount":"16.828767123287671233","interestPayment":{"hasExpiredPayments":false,"hasPendingPayments":true,"liquidationRisk":"none","pendingInterestPaymentAmount":"16.828767123287671233"},"isModifiable":false,"isUserApprovalRequired":false,"liquidationPriceReference":"35542.305882352941176471","loanAmount":"1641.828767123287671233","loanAmountConverted":"1510.482465753424657534","loanCurrency":"USDC","loanOriginalAmount":"1625.000000000000000000","ltv":"0.5052","maxLoanAmount":null,"minLoanAmount":null,"orderId":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","paybackAmount":"0.000000000000000000","paybackAmountConverted":"0.000000000000000000","paybackInterestAmount":"0.000000000000000000","paybackPrincipalAmount":"0.000000000000000000","remainingAmount":"1641.828767123287671233","remainingAmountConverted":"1510.482465753424657534","remainingInterestAmount":"16.828767123287671233","remainingPrincipalAmount":"1625.000000000000000000","requestedByUserId":"5a235979-dbfe-4830-8dbd-c85548bcfcf4","startedAt":"2026-09-07T10:15:31.480Z","status":"active","updatedAt":"2026-10-07T00:00:12.345Z","userId":"5a235979-dbfe-4830-8dbd-c85548bcfcf4"},"schema":{"allOf":[{"description":"A loan order. Amounts are decimal strings, usually with 18 decimals, in the currency named by\nthe matching `guaranteeCurrency` or `loanCurrency`; `ltv` and `apr` are fractions with 4\ndecimals (`0.5000` is 50 %).\n","properties":{"apr":{"description":"Annual percentage rate of the loan before discounts, fixed at creation from the\nconfiguration of `loanCurrency`. The user-level, recurring interest payment and promotion\ndiscounts are subtracted from it when interest accrues.\n","example":"0.1500","pattern":"^[0-9]+\\.[0-9]{4}$","type":"string"},"createdAt":{"description":"When the order was requested.","example":"2026-09-07T10:15:30.120Z","format":"date-time","type":"string"},"expiresAt":{"description":"Deadline for a `pending` order to be approved; past it, the order becomes `expired`. It is\nset at creation on every order but only matters while the order is `pending`.\n","example":"2026-09-10T10:15:30.118Z","format":"date-time","nullable":true,"type":"string"},"finishedAt":{"description":"When the order was closed, by completion, rejection, expiration or liquidation. `null`\nwhile it is open.\n","example":"2027-03-12T16:40:21.905Z","format":"date-time","nullable":true,"type":"string"},"guaranteeAmount":{"description":"Guarantee locked now. Guarantee increases add to it; guarantee decreases and liquidations\ntake from it.\n","example":"0.050000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"guaranteeCurrency":{"description":"Symbol of the currency locked as guarantee.","example":"BTC","type":"string"},"guaranteeOriginalAmount":{"description":"Guarantee locked when the order was created. It never changes afterwards.","example":"0.050000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"hasRecurringInterestPayment":{"description":"`true` when the interest is paid every month, which earns the recurring interest payment\ndiscount; `false` when all the interest is paid at the end.\n","example":true,"type":"boolean"},"interestAmount":{"description":"Interest accrued so far, after discounts. It is already included in `loanAmount`.","example":"16.828767123287671233","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"isModifiable":{"description":"Whether the loan amount and the guarantee can still be changed when the user approves a\nloan offered by Bit2Me, within `minLoanAmount` and `maxLoanAmount`. `false` for loans the\nuser requests.\n","example":false,"type":"boolean"},"loanAmount":{"description":"Debt accrued so far: `loanOriginalAmount` plus `interestAmount`. Repayments do not reduce\nit; the debt still to repay is `loanAmount - paybackAmount`.\n","example":"1641.828767123287671233","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"loanCurrency":{"description":"Symbol of the currency lent.","example":"USDC","type":"string"},"loanOriginalAmount":{"description":"Amount lent when the order was created, that is, the principal.","example":"1625.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"ltv":{"description":"Loan-to-value: the debt still to repay divided by the value of `guaranteeAmount`, both at\ncurrent prices. It is recalculated on every operation and periodically as prices move;\nwhen it reaches the `liquidationLtv` of the guarantee currency (see\n`GET /v2/loan/currency/configuration`) the guarantee is sold.\n","example":"0.5052","pattern":"^[0-9]+\\.[0-9]{4}$","type":"string"},"maxLoanAmount":{"description":"Highest loan amount, in `loanCurrency`, accepted when modifying the order on approval.\n`null` when no bound was set; only relevant when `isModifiable` is `true`.\n","example":"2000.000000000000000000","nullable":true,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"minLoanAmount":{"description":"Lowest loan amount, in `loanCurrency`, accepted when modifying the order on approval.\n`null` when no bound was set; only relevant when `isModifiable` is `true`.\n","example":"1000.000000000000000000","nullable":true,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"orderId":{"description":"Identifier of the loan order.","example":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","format":"uuid","type":"string"},"paybackAmount":{"description":"Total repaid so far, `paybackPrincipalAmount` plus `paybackInterestAmount`.","example":"0.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"paybackInterestAmount":{"description":"Part of `paybackAmount` that went to interest. Every repayment pays the accrued interest\nbefore the principal.\n","example":"0.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"paybackPrincipalAmount":{"description":"Part of `paybackAmount` that went to the principal.","example":"0.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"requestedByUserId":{"description":"Who created the order. It equals `userId` for loans the user requested themselves, and\ndiffers for loans Bit2Me offered to the user, which stay `pending` until the user\napproves them (see `isUserApprovalRequired`).\n","example":"5a235979-dbfe-4830-8dbd-c85548bcfcf4","format":"uuid","type":"string"},"startedAt":{"description":"When the order was approved and the loan paid out. `null` until then.","example":"2026-09-07T10:15:31.480Z","format":"date-time","nullable":true,"type":"string"},"status":{"description":"Where the order is in its lifecycle:\n\n- `pending`: created but not active. Loans the user requests are approved at once, so this\n  is mostly seen on loans offered by Bit2Me that wait for the user's approval. It turns\n  `expired` at `expiresAt`.\n- `active`: the loan was paid out and accrues interest.\n- `completed`: fully repaid; the guarantee was returned to the wallet.\n- `pending-liquidation`: the guarantee is being sold, because the LTV reached the\n  liquidation threshold or an interest payment expired.\n- `liquidated`: the liquidation finished.\n- `rejected`: a pending order was rejected.\n- `expired`: a pending order was not approved before `expiresAt`.\n","enum":["pending","active","rejected","completed","liquidated","expired","pending-liquidation"],"example":"active","type":"string"},"updatedAt":{"description":"When the order last changed. Interest accrual and LTV updates move it too, so it is not a\nsign of user activity.\n","example":"2026-10-07T00:00:12.345Z","format":"date-time","type":"string"},"userId":{"description":"The borrower, that is, the authenticated user.","example":"5a235979-dbfe-4830-8dbd-c85548bcfcf4","format":"uuid","type":"string"}},"required":["orderId","createdAt","updatedAt","userId","requestedByUserId","guaranteeCurrency","guaranteeOriginalAmount","guaranteeAmount","loanCurrency","loanOriginalAmount","loanAmount","paybackAmount","ltv","apr","status","paybackPrincipalAmount","paybackInterestAmount","interestAmount","hasRecurringInterestPayment","isModifiable"],"type":"object"},{"properties":{"aprDetails":{"allOf":[{"description":"How the APR of a loan is built: `finalApr = baseApr - totalDiscount`, where `totalDiscount`\nadds up the reductions listed in `aprDiscounts`. All rates are fractions with 4 decimals\n(`0.1500` is 15 %).\n","properties":{"aprDiscounts":{"description":"Reductions applied, in the order they are applied: recurring interest payment, user level,\nthen promotion. A promotion that overrides all discounts is the only entry. Empty when no\nreduction applies.\n","items":{"description":"One reduction applied to the APR.","properties":{"discountAmount":{"description":"APR points removed by this reduction, as a fraction with 4 decimals (`0.0140` is 1.4\npoints). It is subtracted from the APR, not multiplied by it.\n","example":"0.0140","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"type":{"description":"Origin of the reduction: `recurring-interest-payment` for paying interest monthly,\n`user-level` for the user's Bit2Me level, `promotion` for an APR promotion of the order.\n","enum":["user-level","recurring-interest-payment","promotion"],"example":"user-level","type":"string"}},"required":["type","discountAmount"],"type":"object"},"type":"array"},"baseApr":{"description":"APR before any reduction. For a loan order it is the order's `apr`.","example":"0.1500","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"finalApr":{"description":"APR the loan actually accrues interest at, after every reduction. Never negative.","example":"0.1260","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"interestPaymentDiscount":{"description":"APR points removed from loans that pay interest monthly (`0.0100` is one point). It is the\nconfigured value and is returned even when the loan does not pay interest monthly; whether\nit was applied is shown by a `recurring-interest-payment` entry in `aprDiscounts`.\n","example":"0.0100","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"isCustomUserLevel":{"description":"`true` when the user's level discount was set specifically for them instead of coming from\ntheir Bit2Me level.\n","example":false,"type":"boolean"},"promotion":{"allOf":[{"description":"APR promotion attached to a loan order.","properties":{"discount":{"description":"Configured promotion discount value (0-1 range). Interpretation depends on discountType: when percentage, this fraction of the remaining APR is removed; when absolute, this value is subtracted directly from the remaining APR.\n","example":"0.0500","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"discountAmount":{"description":"Resolved absolute APR reduction after applying the configured discount.\n","example":"0.0014","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"discountType":{"description":"Whether the discount is a percentage of the remaining APR or an absolute APR reduction.\n","enum":["percentage","absolute"],"example":"percentage","type":"string"},"durationDays":{"description":"Promotion duration in days. `null` when the promotion has no fixed duration.","example":30,"nullable":true,"type":"integer"},"endDate":{"description":"When the promotion stops applying. Absent when it has no end date.","example":"2026-10-07T10:15:31.480Z","format":"date-time","type":"string"},"overridesAllDiscounts":{"description":"When true, the promotion overrides all other discounts (user-level and recurring interest payment); when false, it is applied on top of the other discounts.\n","example":false,"type":"boolean"}},"required":["discount","discountType","overridesAllDiscounts","discountAmount"],"type":"object"}],"description":"APR promotion of the loan. Absent when it has none."},"totalDiscount":{"description":"Sum of the reductions in `aprDiscounts`.","example":"0.0240","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"userDiscount":{"description":"APR points removed for the user's level. It is the user's discount rate applied to the APR\nleft after the recurring interest payment discount, so it is an absolute reduction, not a\nrate. `0.0000` when the user has no level discount or a promotion overrides it.\n","example":"0.0140","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["userDiscount","isCustomUserLevel","interestPaymentDiscount","totalDiscount","baseApr","finalApr","aprDiscounts"],"type":"object"}],"description":"How the APR of the order was obtained. When the breakdown is not available, `baseApr`\nand `finalApr` are `apr` and there are no discounts.\n"},"discount":{"description":"The same as `aprDetails.userDiscount`. Present only when it is greater than `0`.","example":"0.0140","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"guaranteeAmountConverted":{"description":"Value of `guaranteeAmount` in EUR.","example":"2990.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"hasActiveAprPromotion":{"description":"Whether an APR promotion is applied to the order.","example":false,"type":"boolean"},"interestPayment":{"description":"State of the monthly interest payments of the loan. When an interest payment goes unpaid, the\nnext one carries the date on which the order will be liquidated. Without interest payments\nevery flag is `false` and the amount is `0`.\n","properties":{"expiredPaymentLiquidationDate":{"description":"When the order will be liquidated unless the pending interest is paid. Present only when\n`hasExpiredPayments` is `true`.\n","example":"2026-11-01T00:00:00.000Z","format":"date-time","type":"string"},"hasExpiredPayments":{"description":"Whether an earlier interest payment went unpaid, so a liquidation date is set.","example":false,"type":"boolean"},"hasPendingPayments":{"description":"Whether the interest payment of the current period is still unpaid.","example":true,"type":"boolean"},"liquidationRisk":{"description":"Risk of liquidation because of unpaid interest:\n\n- `none`: no liquidation date is set.\n- `medium`: the liquidation date falls in a later month.\n- `high`: the liquidation date falls in the current month or has passed.\n","enum":["none","medium","high"],"example":"none","type":"string"},"pendingInterestPaymentAmount":{"description":"Interest pending of payment, in the loan currency. `0` when nothing is pending.","example":"16.828767123287671233","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["hasExpiredPayments","hasPendingPayments","pendingInterestPaymentAmount","liquidationRisk"],"type":"object"},"isUserApprovalRequired":{"description":"Whether the order is a loan offer waiting for the user's approval: it is `pending` and\nwas requested by someone other than the user.\n","example":false,"type":"boolean"},"liquidationPriceReference":{"description":"Price of one unit of the guarantee currency, in EUR, at which the order would reach an\nLTV of `0.85`.\n","example":"35542.305882352941176471","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"loanAmountConverted":{"description":"Value of `loanAmount` in EUR.","example":"1510.482465753424657534","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"paybackAmountConverted":{"description":"Value of `paybackAmount` in EUR.","example":"0.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"remainingAmount":{"description":"Debt left to repay, `loanAmount` minus `paybackAmount`, in the loan currency.","example":"1641.828767123287671233","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"remainingAmountConverted":{"description":"Value of `remainingAmount` in EUR.","example":"1510.482465753424657534","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"remainingInterestAmount":{"description":"Interest left to repay, `interestAmount` minus `paybackInterestAmount`, never below `0`.","example":"16.828767123287671233","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"remainingPrincipalAmount":{"description":"Principal left to repay, `loanOriginalAmount` minus `paybackPrincipalAmount`.","example":"1625.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["remainingAmount","remainingPrincipalAmount","remainingInterestAmount","liquidationPriceReference","loanAmountConverted","guaranteeAmountConverted","paybackAmountConverted","remainingAmountConverted","isUserApprovalRequired","hasActiveAprPromotion","interestPayment","aprDetails"],"type":"object"}],"description":"A loan order with its values in EUR at current prices and what is left to repay. When the order\nis `liquidated`, the remaining amounts are `0`.\n"}}},"description":"The loan order."},"400":{"content":{"application/json":{"example":{"error":"Bad Request","message":"Validation failed (uuid v 4 is expected)","statusCode":400},"schema":{"description":"Error returned by the loan endpoints. Unlike the field validation error, `message` is a single\nstring; it is meant for logs, so branch on the HTTP status rather than on its text.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong.","example":"OrderId 7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message","error"],"type":"object"}}},"description":"`orderId` is not a UUID v4."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The JWT or the API key (with its signature and nonce) could not be validated."},"404":{"content":{"application/json":{"example":{"error":"Not Found","message":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","statusCode":404},"schema":{"description":"Error returned by the loan endpoints. Unlike the field validation error, `message` is a single\nstring; it is meant for logs, so branch on the HTTP status rather than on its text.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong.","example":"OrderId 7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message","error"],"type":"object"}}},"description":"The user has no loan order with this `orderId`. `message` is the `orderId`."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get loan order by ID","tags":["Loan"],"x-product":{"wallet":"Loan"}}},"/v1/loan/orders/{orderId}/guarantee/increase":{"post":{"description":"Adds guarantee to an `active` loan, taking it from the user's wallet, which lowers the LTV and\nthe liquidation price. The response returns the updated order and the `guarantee_increase`\nmovement created; `guaranteeOriginalAmount` does not change.\n","parameters":[{"description":"Identifier of the loan order, a UUID v4.","example":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","in":"path","name":"orderId","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"guaranteeAmount":"0.01"},"schema":{"properties":{"guaranteeAmount":{"description":"Amount to add to the guarantee, in the guarantee currency of the order. It is taken from\nthe user's wallet.\n","example":"0.01","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["guaranteeAmount"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"example":{"apr":"0.1500","createdAt":"2026-09-07T10:15:30.120Z","createdMovements":[{"movementId":"5c8d2f71-0e4b-4a93-b6d7-1f2a9e3c8b54","status":"completed","type":"guarantee_increase"}],"expiresAt":"2026-09-10T10:15:30.118Z","finishedAt":null,"guaranteeAmount":"0.060000000000000000","guaranteeCurrency":"BTC","guaranteeOriginalAmount":"0.050000000000000000","hasRecurringInterestPayment":true,"interestAmount":"16.828767123287671233","isModifiable":false,"loanAmount":"1641.828767123287671233","loanCurrency":"USDC","loanOriginalAmount":"1625.000000000000000000","ltv":"0.4210","maxLoanAmount":null,"minLoanAmount":null,"orderId":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","paybackAmount":"0.000000000000000000","paybackInterestAmount":"0.000000000000000000","paybackPrincipalAmount":"0.000000000000000000","requestedByUserId":"5a235979-dbfe-4830-8dbd-c85548bcfcf4","startedAt":"2026-09-07T10:15:31.480Z","status":"active","updatedAt":"2026-10-07T09:45:12.034Z","userId":"5a235979-dbfe-4830-8dbd-c85548bcfcf4"},"schema":{"allOf":[{"description":"A loan order. Amounts are decimal strings, usually with 18 decimals, in the currency named by\nthe matching `guaranteeCurrency` or `loanCurrency`; `ltv` and `apr` are fractions with 4\ndecimals (`0.5000` is 50 %).\n","properties":{"apr":{"description":"Annual percentage rate of the loan before discounts, fixed at creation from the\nconfiguration of `loanCurrency`. The user-level, recurring interest payment and promotion\ndiscounts are subtracted from it when interest accrues.\n","example":"0.1500","pattern":"^[0-9]+\\.[0-9]{4}$","type":"string"},"createdAt":{"description":"When the order was requested.","example":"2026-09-07T10:15:30.120Z","format":"date-time","type":"string"},"expiresAt":{"description":"Deadline for a `pending` order to be approved; past it, the order becomes `expired`. It is\nset at creation on every order but only matters while the order is `pending`.\n","example":"2026-09-10T10:15:30.118Z","format":"date-time","nullable":true,"type":"string"},"finishedAt":{"description":"When the order was closed, by completion, rejection, expiration or liquidation. `null`\nwhile it is open.\n","example":"2027-03-12T16:40:21.905Z","format":"date-time","nullable":true,"type":"string"},"guaranteeAmount":{"description":"Guarantee locked now. Guarantee increases add to it; guarantee decreases and liquidations\ntake from it.\n","example":"0.050000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"guaranteeCurrency":{"description":"Symbol of the currency locked as guarantee.","example":"BTC","type":"string"},"guaranteeOriginalAmount":{"description":"Guarantee locked when the order was created. It never changes afterwards.","example":"0.050000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"hasRecurringInterestPayment":{"description":"`true` when the interest is paid every month, which earns the recurring interest payment\ndiscount; `false` when all the interest is paid at the end.\n","example":true,"type":"boolean"},"interestAmount":{"description":"Interest accrued so far, after discounts. It is already included in `loanAmount`.","example":"16.828767123287671233","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"isModifiable":{"description":"Whether the loan amount and the guarantee can still be changed when the user approves a\nloan offered by Bit2Me, within `minLoanAmount` and `maxLoanAmount`. `false` for loans the\nuser requests.\n","example":false,"type":"boolean"},"loanAmount":{"description":"Debt accrued so far: `loanOriginalAmount` plus `interestAmount`. Repayments do not reduce\nit; the debt still to repay is `loanAmount - paybackAmount`.\n","example":"1641.828767123287671233","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"loanCurrency":{"description":"Symbol of the currency lent.","example":"USDC","type":"string"},"loanOriginalAmount":{"description":"Amount lent when the order was created, that is, the principal.","example":"1625.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"ltv":{"description":"Loan-to-value: the debt still to repay divided by the value of `guaranteeAmount`, both at\ncurrent prices. It is recalculated on every operation and periodically as prices move;\nwhen it reaches the `liquidationLtv` of the guarantee currency (see\n`GET /v2/loan/currency/configuration`) the guarantee is sold.\n","example":"0.5052","pattern":"^[0-9]+\\.[0-9]{4}$","type":"string"},"maxLoanAmount":{"description":"Highest loan amount, in `loanCurrency`, accepted when modifying the order on approval.\n`null` when no bound was set; only relevant when `isModifiable` is `true`.\n","example":"2000.000000000000000000","nullable":true,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"minLoanAmount":{"description":"Lowest loan amount, in `loanCurrency`, accepted when modifying the order on approval.\n`null` when no bound was set; only relevant when `isModifiable` is `true`.\n","example":"1000.000000000000000000","nullable":true,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"orderId":{"description":"Identifier of the loan order.","example":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","format":"uuid","type":"string"},"paybackAmount":{"description":"Total repaid so far, `paybackPrincipalAmount` plus `paybackInterestAmount`.","example":"0.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"paybackInterestAmount":{"description":"Part of `paybackAmount` that went to interest. Every repayment pays the accrued interest\nbefore the principal.\n","example":"0.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"paybackPrincipalAmount":{"description":"Part of `paybackAmount` that went to the principal.","example":"0.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"requestedByUserId":{"description":"Who created the order. It equals `userId` for loans the user requested themselves, and\ndiffers for loans Bit2Me offered to the user, which stay `pending` until the user\napproves them (see `isUserApprovalRequired`).\n","example":"5a235979-dbfe-4830-8dbd-c85548bcfcf4","format":"uuid","type":"string"},"startedAt":{"description":"When the order was approved and the loan paid out. `null` until then.","example":"2026-09-07T10:15:31.480Z","format":"date-time","nullable":true,"type":"string"},"status":{"description":"Where the order is in its lifecycle:\n\n- `pending`: created but not active. Loans the user requests are approved at once, so this\n  is mostly seen on loans offered by Bit2Me that wait for the user's approval. It turns\n  `expired` at `expiresAt`.\n- `active`: the loan was paid out and accrues interest.\n- `completed`: fully repaid; the guarantee was returned to the wallet.\n- `pending-liquidation`: the guarantee is being sold, because the LTV reached the\n  liquidation threshold or an interest payment expired.\n- `liquidated`: the liquidation finished.\n- `rejected`: a pending order was rejected.\n- `expired`: a pending order was not approved before `expiresAt`.\n","enum":["pending","active","rejected","completed","liquidated","expired","pending-liquidation"],"example":"active","type":"string"},"updatedAt":{"description":"When the order last changed. Interest accrual and LTV updates move it too, so it is not a\nsign of user activity.\n","example":"2026-10-07T00:00:12.345Z","format":"date-time","type":"string"},"userId":{"description":"The borrower, that is, the authenticated user.","example":"5a235979-dbfe-4830-8dbd-c85548bcfcf4","format":"uuid","type":"string"}},"required":["orderId","createdAt","updatedAt","userId","requestedByUserId","guaranteeCurrency","guaranteeOriginalAmount","guaranteeAmount","loanCurrency","loanOriginalAmount","loanAmount","paybackAmount","ltv","apr","status","paybackPrincipalAmount","paybackInterestAmount","interestAmount","hasRecurringInterestPayment","isModifiable"],"type":"object"},{"properties":{"createdMovements":{"description":"Movements created by the operation: `request` and `approve` when an order is created,\n`payback` for a repayment and `guarantee_increase` when guarantee is added. This list is\nonly returned in the response of the operation.\n","items":{"description":"A movement created by the operation.","properties":{"movementId":{"description":"Identifier of the movement.","example":"3d6f0a52-8c1e-4b7a-9f2d-6e5c4b3a2f10","format":"uuid","type":"string"},"status":{"description":"Progress of the movement. `completed` and `canceled` are final; the other values are\nintermediate steps of the funds transfers.\n","enum":["pending","completed","guarantee_received","loan_issued","loan_received","guarantee_returned","guarantee_sold","guarantee_withdrawn","guarantee_swapped","canceled"],"example":"completed","type":"string"},"type":{"description":"What the movement did:\n\n- `request`: the loan was requested.\n- `approve`: the loan was approved and issued.\n- `reject`: the loan was rejected.\n- `expire`: the loan request expired before being approved.\n- `payback`: part or all of the debt was repaid.\n- `payback_guarantee`: debt repaid by selling part of the guarantee.\n- `guarantee_increase`: guarantee was added.\n- `guarantee_decrease`: guarantee was withdrawn.\n- `liquidate`: the guarantee was sold to cancel the debt.\n- `loan_currency_migration`: the loan was moved to another loan currency by Bit2Me.\n","enum":["request","approve","reject","payback","liquidate","guarantee_increase","guarantee_decrease","expire","payback_guarantee","loan_currency_migration"],"example":"guarantee_increase","type":"string"}},"required":["movementId","type","status"],"type":"object"},"type":"array"}},"required":["createdMovements"],"type":"object"}]}}},"description":"The guarantee was added."},"400":{"content":{"application/json":{"example":{"error":"Bad Request","message":["guaranteeAmount must be a positive number string"],"statusCode":400},"schema":{"description":"Returned with `400` when the request is rejected field by field rather than against the\npublished contract. It is not the same shape as the contract validation error, and the\ndifference that catches integrators out is that **`message` is an array of strings here**,\nwhile everywhere else it is a single string.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"One human-readable sentence per failed constraint.","example":["iban should not be empty","iban must be a string"],"items":{"type":"string"},"type":"array"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["message","error","statusCode"],"type":"object"}}},"description":"The body is not valid; `message` lists every failed constraint."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The JWT or the API key (with its signature and nonce) could not be validated."},"404":{"content":{"application/json":{"example":{"error":"Not Found","message":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","statusCode":404},"schema":{"description":"Error returned by the loan endpoints. Unlike the field validation error, `message` is a single\nstring; it is meant for logs, so branch on the HTTP status rather than on its text.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong.","example":"OrderId 7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message","error"],"type":"object"}}},"description":"The user has no `active` loan order with this `orderId`. `message` is the `orderId`."},"412":{"content":{"application/json":{"examples":{"maximumRisk":{"summary":"LTV still at liquidation level","value":{"error":"Precondition Failed","message":"loan to value exceeds maximum risk: 0.8612","statusCode":412}},"notEnoughFunds":{"summary":"Not enough funds in the wallet","value":{"error":"Precondition Failed","message":"not enough funds in wallet for user 5a235979-dbfe-4830-8dbd-c85548bcfcf4 - error retrieving 0.01 BTC funds from wallet","statusCode":412}}},"schema":{"description":"Error returned by the loan endpoints. Unlike the field validation error, `message` is a single\nstring; it is meant for logs, so branch on the HTTP status rather than on its text.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong.","example":"OrderId 7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message","error"],"type":"object"}}},"description":"The guarantee cannot be added: the wallet does not hold `guaranteeAmount`, or the resulting\nLTV would still be at or above the liquidation threshold or would be negative.\n"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Increase loan guarantee","tags":["Loan"],"x-product":{"wallet":"Loan"}}},"/v1/loan/orders/{orderId}/payback":{"post":{"description":"Repays part or all of an `active` loan with funds of the loan currency taken from the user's\nwallet. Accrued interest is paid first and the rest reduces the principal.\n\nWhen `paybackAmount` covers the remaining debt, only the remaining debt is charged, the order\nbecomes `completed` and the guarantee is returned to the wallet. The response returns the\nupdated order and the `payback` movement created.\n","parameters":[{"description":"Identifier of the loan order, a UUID v4.","example":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","in":"path","name":"orderId","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"paybackAmount":"500"},"schema":{"properties":{"paybackAmount":{"description":"Amount to repay, in the loan currency of the order, taken from the user's wallet. It pays\nthe accrued interest first and then the principal. When it covers the whole remaining debt\nthe loan is completed: only the remaining debt is charged and the guarantee is returned to\nthe wallet.\n","example":"500","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["paybackAmount"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"example":{"apr":"0.1500","createdAt":"2026-09-07T10:15:30.120Z","createdMovements":[{"movementId":"3d6f0a52-8c1e-4b7a-9f2d-6e5c4b3a2f10","status":"completed","type":"payback"}],"expiresAt":"2026-09-10T10:15:30.118Z","finishedAt":null,"guaranteeAmount":"0.050000000000000000","guaranteeCurrency":"BTC","guaranteeOriginalAmount":"0.050000000000000000","hasRecurringInterestPayment":true,"interestAmount":"16.828767123287671233","isModifiable":false,"loanAmount":"1641.828767123287671233","loanCurrency":"USDC","loanOriginalAmount":"1625.000000000000000000","ltv":"0.3513","maxLoanAmount":null,"minLoanAmount":null,"orderId":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","paybackAmount":"500.000000000000000000","paybackInterestAmount":"16.828767123287671233","paybackPrincipalAmount":"483.171232876712328767","requestedByUserId":"5a235979-dbfe-4830-8dbd-c85548bcfcf4","startedAt":"2026-09-07T10:15:31.480Z","status":"active","updatedAt":"2026-10-07T09:30:05.210Z","userId":"5a235979-dbfe-4830-8dbd-c85548bcfcf4"},"schema":{"allOf":[{"description":"A loan order. Amounts are decimal strings, usually with 18 decimals, in the currency named by\nthe matching `guaranteeCurrency` or `loanCurrency`; `ltv` and `apr` are fractions with 4\ndecimals (`0.5000` is 50 %).\n","properties":{"apr":{"description":"Annual percentage rate of the loan before discounts, fixed at creation from the\nconfiguration of `loanCurrency`. The user-level, recurring interest payment and promotion\ndiscounts are subtracted from it when interest accrues.\n","example":"0.1500","pattern":"^[0-9]+\\.[0-9]{4}$","type":"string"},"createdAt":{"description":"When the order was requested.","example":"2026-09-07T10:15:30.120Z","format":"date-time","type":"string"},"expiresAt":{"description":"Deadline for a `pending` order to be approved; past it, the order becomes `expired`. It is\nset at creation on every order but only matters while the order is `pending`.\n","example":"2026-09-10T10:15:30.118Z","format":"date-time","nullable":true,"type":"string"},"finishedAt":{"description":"When the order was closed, by completion, rejection, expiration or liquidation. `null`\nwhile it is open.\n","example":"2027-03-12T16:40:21.905Z","format":"date-time","nullable":true,"type":"string"},"guaranteeAmount":{"description":"Guarantee locked now. Guarantee increases add to it; guarantee decreases and liquidations\ntake from it.\n","example":"0.050000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"guaranteeCurrency":{"description":"Symbol of the currency locked as guarantee.","example":"BTC","type":"string"},"guaranteeOriginalAmount":{"description":"Guarantee locked when the order was created. It never changes afterwards.","example":"0.050000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"hasRecurringInterestPayment":{"description":"`true` when the interest is paid every month, which earns the recurring interest payment\ndiscount; `false` when all the interest is paid at the end.\n","example":true,"type":"boolean"},"interestAmount":{"description":"Interest accrued so far, after discounts. It is already included in `loanAmount`.","example":"16.828767123287671233","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"isModifiable":{"description":"Whether the loan amount and the guarantee can still be changed when the user approves a\nloan offered by Bit2Me, within `minLoanAmount` and `maxLoanAmount`. `false` for loans the\nuser requests.\n","example":false,"type":"boolean"},"loanAmount":{"description":"Debt accrued so far: `loanOriginalAmount` plus `interestAmount`. Repayments do not reduce\nit; the debt still to repay is `loanAmount - paybackAmount`.\n","example":"1641.828767123287671233","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"loanCurrency":{"description":"Symbol of the currency lent.","example":"USDC","type":"string"},"loanOriginalAmount":{"description":"Amount lent when the order was created, that is, the principal.","example":"1625.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"ltv":{"description":"Loan-to-value: the debt still to repay divided by the value of `guaranteeAmount`, both at\ncurrent prices. It is recalculated on every operation and periodically as prices move;\nwhen it reaches the `liquidationLtv` of the guarantee currency (see\n`GET /v2/loan/currency/configuration`) the guarantee is sold.\n","example":"0.5052","pattern":"^[0-9]+\\.[0-9]{4}$","type":"string"},"maxLoanAmount":{"description":"Highest loan amount, in `loanCurrency`, accepted when modifying the order on approval.\n`null` when no bound was set; only relevant when `isModifiable` is `true`.\n","example":"2000.000000000000000000","nullable":true,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"minLoanAmount":{"description":"Lowest loan amount, in `loanCurrency`, accepted when modifying the order on approval.\n`null` when no bound was set; only relevant when `isModifiable` is `true`.\n","example":"1000.000000000000000000","nullable":true,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"orderId":{"description":"Identifier of the loan order.","example":"7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01","format":"uuid","type":"string"},"paybackAmount":{"description":"Total repaid so far, `paybackPrincipalAmount` plus `paybackInterestAmount`.","example":"0.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"paybackInterestAmount":{"description":"Part of `paybackAmount` that went to interest. Every repayment pays the accrued interest\nbefore the principal.\n","example":"0.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"paybackPrincipalAmount":{"description":"Part of `paybackAmount` that went to the principal.","example":"0.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"requestedByUserId":{"description":"Who created the order. It equals `userId` for loans the user requested themselves, and\ndiffers for loans Bit2Me offered to the user, which stay `pending` until the user\napproves them (see `isUserApprovalRequired`).\n","example":"5a235979-dbfe-4830-8dbd-c85548bcfcf4","format":"uuid","type":"string"},"startedAt":{"description":"When the order was approved and the loan paid out. `null` until then.","example":"2026-09-07T10:15:31.480Z","format":"date-time","nullable":true,"type":"string"},"status":{"description":"Where the order is in its lifecycle:\n\n- `pending`: created but not active. Loans the user requests are approved at once, so this\n  is mostly seen on loans offered by Bit2Me that wait for the user's approval. It turns\n  `expired` at `expiresAt`.\n- `active`: the loan was paid out and accrues interest.\n- `completed`: fully repaid; the guarantee was returned to the wallet.\n- `pending-liquidation`: the guarantee is being sold, because the LTV reached the\n  liquidation threshold or an interest payment expired.\n- `liquidated`: the liquidation finished.\n- `rejected`: a pending order was rejected.\n- `expired`: a pending order was not approved before `expiresAt`.\n","enum":["pending","active","rejected","completed","liquidated","expired","pending-liquidation"],"example":"active","type":"string"},"updatedAt":{"description":"When the order last changed. Interest accrual and LTV updates move it too, so it is not a\nsign of user activity.\n","example":"2026-10-07T00:00:12.345Z","format":"date-time","type":"string"},"userId":{"description":"The borrower, that is, the authenticated user.","example":"5a235979-dbfe-4830-8dbd-c85548bcfcf4","format":"uuid","type":"string"}},"required":["orderId","createdAt","updatedAt","userId","requestedByUserId","guaranteeCurrency","guaranteeOriginalAmount","guaranteeAmount","loanCurrency","loanOriginalAmount","loanAmount","paybackAmount","ltv","apr","status","paybackPrincipalAmount","paybackInterestAmount","interestAmount","hasRecurringInterestPayment","isModifiable"],"type":"object"},{"properties":{"createdMovements":{"description":"Movements created by the operation: `request` and `approve` when an order is created,\n`payback` for a repayment and `guarantee_increase` when guarantee is added. This list is\nonly returned in the response of the operation.\n","items":{"description":"A movement created by the operation.","properties":{"movementId":{"description":"Identifier of the movement.","example":"3d6f0a52-8c1e-4b7a-9f2d-6e5c4b3a2f10","format":"uuid","type":"string"},"status":{"description":"Progress of the movement. `completed` and `canceled` are final; the other values are\nintermediate steps of the funds transfers.\n","enum":["pending","completed","guarantee_received","loan_issued","loan_received","guarantee_returned","guarantee_sold","guarantee_withdrawn","guarantee_swapped","canceled"],"example":"completed","type":"string"},"type":{"description":"What the movement did:\n\n- `request`: the loan was requested.\n- `approve`: the loan was approved and issued.\n- `reject`: the loan was rejected.\n- `expire`: the loan request expired before being approved.\n- `payback`: part or all of the debt was repaid.\n- `payback_guarantee`: debt repaid by selling part of the guarantee.\n- `guarantee_increase`: guarantee was added.\n- `guarantee_decrease`: guarantee was withdrawn.\n- `liquidate`: the guarantee was sold to cancel the debt.\n- `loan_currency_migration`: the loan was moved to another loan currency by Bit2Me.\n","enum":["request","approve","reject","payback","liquidate","guarantee_increase","guarantee_decrease","expire","payback_guarantee","loan_currency_migration"],"example":"guarantee_increase","type":"string"}},"required":["movementId","type","status"],"type":"object"},"type":"array"}},"required":["createdMovements"],"type":"object"}]}}},"description":"The repayment was applied."},"400":{"content":{"application/json":{"example":{"error":"Bad Request","message":["paybackAmount must be a positive number string"],"statusCode":400},"schema":{"description":"Returned with `400` when the request is rejected field by field rather than against the\npublished contract. It is not the same shape as the contract validation error, and the\ndifference that catches integrators out is that **`message` is an array of strings here**,\nwhile everywhere else it is a single string.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"One human-readable sentence per failed constraint.","example":["iban should not be empty","iban must be a string"],"items":{"type":"string"},"type":"array"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["message","error","statusCode"],"type":"object"}}},"description":"The body is not valid; `message` lists every failed constraint."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The JWT or the API key (with its signature and nonce) could not be validated."},"404":{"content":{"application/json":{"example":{"error":"Not Found","message":"OrderId 7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01 not found","statusCode":404},"schema":{"description":"Error returned by the loan endpoints. Unlike the field validation error, `message` is a single\nstring; it is meant for logs, so branch on the HTTP status rather than on its text.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong.","example":"OrderId 7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message","error"],"type":"object"}}},"description":"The user has no `active` loan order with this `orderId`."},"412":{"content":{"application/json":{"examples":{"maximumRisk":{"summary":"LTV still at liquidation level","value":{"date":"2026-10-07T09:30:05.512Z","errorCode":"B2M_LOAN_LTV_MAXIMUM_RISK","errorType":"GENERIC","message":"loan to value exceeds maximum risk: 0.8612","requestId":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd"}},"negativeLtv":{"summary":"Resulting LTV would be negative","value":{"date":"2026-10-07T09:30:05.512Z","errorCode":"B2M_LOAN_LTV_NEGATIVE","errorType":"GENERIC","message":"loan to value is negative: -0.0012","requestId":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd"}},"notEnoughFunds":{"summary":"Not enough funds in the wallet","value":{"date":"2026-10-07T09:30:05.512Z","errorCode":"B2M_LOAN_NOT_ENOUGH_FUNDS","errorType":"GENERIC","message":"not enough funds in wallet for user 5a235979-dbfe-4830-8dbd-c85548bcfcf4 - error retrieving 500 USDC funds from wallet","requestId":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd"}}},"schema":{"properties":{"date":{"description":"When the error was produced (ISO 8601)","example":"2025-11-11T11:11:11.111Z","format":"date-time","type":"string"},"errorCode":{"description":"Stable, machine-readable error identifier. Branch on this, never on `message`.","example":"B2M_BLOCKCHAIN_MANAGER_TRAVEL_RULE_ORDER_NOT_FOUND","type":"string"},"errorType":{"enum":["GENERIC"],"type":"string"},"message":{"description":"Human-readable description of the error, intended for logs rather than end users.","example":"Travel rule order not found: 00000000-0000-4000-8000-000000000000","type":"string"},"requestId":{"description":"Identifier of the request that failed. Quote it when reporting an incident.","example":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd","format":"uuid","type":"string"}},"required":["errorCode","message","errorType","date"],"type":"object"}}},"description":"The repayment cannot be applied:\n\n- `B2M_LOAN_NOT_ENOUGH_FUNDS`: the wallet does not hold `paybackAmount` of the loan\n  currency.\n- `B2M_LOAN_LTV_MAXIMUM_RISK`: after the repayment the LTV would still be at or above the\n  liquidation threshold.\n- `B2M_LOAN_LTV_NEGATIVE`: the resulting LTV would be negative.\n"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Pay back a loan","tags":["Loan"],"x-product":{"wallet":"Loan"}}},"/v1/loan/pre-contract":{"post":{"description":"Renders the current version of the loan contract as an HTML document, so the user can read it\nbefore requesting the loan with `POST /v1/loan/orders`. Nothing is created.\n\nThe document is filled in with the conditions sent in the body and with the authenticated\nuser's name, surname, identity document number, email, phone and residence address. It assumes\nthe 50 % LTV used for new loans and a one-year term. `class` and `style` attributes are removed\nfrom the HTML.\n","requestBody":{"content":{"application/json":{"example":{"apr":"0.1500","guaranteeCurrency":"BTC","guaranteeOriginalAmount":"0.05","hasRecurringInterestPayment":false,"langCode":"es","loanCurrency":"USDC","loanOriginalAmount":"1625.000000000000000000","startedAt":"2026-09-07T10:15:30.120Z"},"schema":{"description":"Terms of the loan the user is about to request, usually the amounts returned by\n`GET /v1/loan/ltv`. The document shows them as sent; the loan is only validated when it is\nrequested with `POST /v1/loan/orders`.\n","properties":{"apr":{"description":"Annual percentage rate as a fraction (`0.1500` is 15 %). The contract shows it as a\npercentage with two decimals.\n","example":"0.1500","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"aprDetails":{"allOf":[{"description":"How the APR of a loan is built: `finalApr = baseApr - totalDiscount`, where `totalDiscount`\nadds up the reductions listed in `aprDiscounts`. All rates are fractions with 4 decimals\n(`0.1500` is 15 %).\n","properties":{"aprDiscounts":{"description":"Reductions applied, in the order they are applied: recurring interest payment, user level,\nthen promotion. A promotion that overrides all discounts is the only entry. Empty when no\nreduction applies.\n","items":{"description":"One reduction applied to the APR.","properties":{"discountAmount":{"description":"APR points removed by this reduction, as a fraction with 4 decimals (`0.0140` is 1.4\npoints). It is subtracted from the APR, not multiplied by it.\n","example":"0.0140","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"type":{"description":"Origin of the reduction: `recurring-interest-payment` for paying interest monthly,\n`user-level` for the user's Bit2Me level, `promotion` for an APR promotion of the order.\n","enum":["user-level","recurring-interest-payment","promotion"],"example":"user-level","type":"string"}},"required":["type","discountAmount"],"type":"object"},"type":"array"},"baseApr":{"description":"APR before any reduction. For a loan order it is the order's `apr`.","example":"0.1500","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"finalApr":{"description":"APR the loan actually accrues interest at, after every reduction. Never negative.","example":"0.1260","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"interestPaymentDiscount":{"description":"APR points removed from loans that pay interest monthly (`0.0100` is one point). It is the\nconfigured value and is returned even when the loan does not pay interest monthly; whether\nit was applied is shown by a `recurring-interest-payment` entry in `aprDiscounts`.\n","example":"0.0100","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"isCustomUserLevel":{"description":"`true` when the user's level discount was set specifically for them instead of coming from\ntheir Bit2Me level.\n","example":false,"type":"boolean"},"promotion":{"allOf":[{"description":"APR promotion attached to a loan order.","properties":{"discount":{"description":"Configured promotion discount value (0-1 range). Interpretation depends on discountType: when percentage, this fraction of the remaining APR is removed; when absolute, this value is subtracted directly from the remaining APR.\n","example":"0.0500","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"discountAmount":{"description":"Resolved absolute APR reduction after applying the configured discount.\n","example":"0.0014","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"discountType":{"description":"Whether the discount is a percentage of the remaining APR or an absolute APR reduction.\n","enum":["percentage","absolute"],"example":"percentage","type":"string"},"durationDays":{"description":"Promotion duration in days. `null` when the promotion has no fixed duration.","example":30,"nullable":true,"type":"integer"},"endDate":{"description":"When the promotion stops applying. Absent when it has no end date.","example":"2026-10-07T10:15:31.480Z","format":"date-time","type":"string"},"overridesAllDiscounts":{"description":"When true, the promotion overrides all other discounts (user-level and recurring interest payment); when false, it is applied on top of the other discounts.\n","example":false,"type":"boolean"}},"required":["discount","discountType","overridesAllDiscounts","discountAmount"],"type":"object"}],"description":"APR promotion of the loan. Absent when it has none."},"totalDiscount":{"description":"Sum of the reductions in `aprDiscounts`.","example":"0.0240","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"userDiscount":{"description":"APR points removed for the user's level. It is the user's discount rate applied to the APR\nleft after the recurring interest payment discount, so it is an absolute reduction, not a\nrate. `0.0000` when the user has no level discount or a promotion overrides it.\n","example":"0.0140","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}},"required":["userDiscount","isCustomUserLevel","interestPaymentDiscount","totalDiscount","baseApr","finalApr","aprDiscounts"],"type":"object"}],"description":"APR breakdown of the loan. When sent, the contract includes the clause describing the\ndiscounts or the promotion that apply; when omitted, that clause states there is no\npromotion.\n"},"guaranteeCurrency":{"description":"Symbol of the currency the user will leave as guarantee.","example":"BTC","type":"string"},"guaranteeOriginalAmount":{"description":"Guarantee amount, in `guaranteeCurrency`. It is printed exactly as sent.","example":"0.05","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"hasRecurringInterestPayment":{"description":"Selects the settlement clause: `true` for interest paid in monthly instalments, `false` for\ninterest paid at maturity.\n","example":false,"type":"boolean"},"langCode":{"description":"Language of the document. `es`, in any letter case, renders it in Spanish; any other value\nrenders it in English.\n","example":"es","type":"string"},"loanCurrency":{"description":"Symbol of the currency the user will borrow.","example":"USDC","type":"string"},"loanOriginalAmount":{"description":"Loan amount, in `loanCurrency`. It is printed exactly as sent.","example":"1625.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"startedAt":{"description":"Start date of the loan. The contract ends one year after it. Clients send the current time.\n","example":"2026-09-07T10:15:30.120Z","format":"date-time","type":"string"}},"required":["langCode","guaranteeCurrency","guaranteeOriginalAmount","loanCurrency","loanOriginalAmount","apr","startedAt","hasRecurringInterestPayment"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"text/html":{"example":"\u003c!DOCTYPE html\u003e\u003chtml lang=\"es\"\u003e\u003chead\u003e\u003cmeta charset=\"utf-8\"\u003e\u003ctitle\u003eContrato de préstamo con garantía\u003c/title\u003e\u003c/head\u003e\u003cbody\u003e\u003ch1\u003eContrato de préstamo con garantía\u003c/h1\u003e\u003cp\u003ePrestatario: Jane Doe, con documento X1234567L, correo jane.doe@example.com y domicilio en Calle Mayor 1, 28013 Madrid.\u003c/p\u003e\u003cp\u003eImporte del préstamo: 1625 USDC. Garantía: 0.05 BTC. TAE: 15,00 %.\u003c/p\u003e\u003c/body\u003e\u003c/html\u003e","schema":{"type":"string"}}},"description":"The pre-contract as an HTML document."},"400":{"content":{"application/json":{"example":{"error":"Bad Request","message":["startedAt must be a valid ISO 8601 date string","property foo should not exist"],"statusCode":400},"schema":{"description":"Returned with `400` when the request is rejected field by field rather than against the\npublished contract. It is not the same shape as the contract validation error, and the\ndifference that catches integrators out is that **`message` is an array of strings here**,\nwhile everywhere else it is a single string.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"One human-readable sentence per failed constraint.","example":["iban should not be empty","iban must be a string"],"items":{"type":"string"},"type":"array"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["message","error","statusCode"],"type":"object"}}},"description":"The body is not valid; `message` lists every failed constraint."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The JWT or the API key (with its signature and nonce) could not be validated."},"404":{"content":{"application/json":{"example":{"error":"Not Found","message":"No active contract version found.","statusCode":404},"schema":{"description":"Error returned by the loan endpoints. Unlike the field validation error, `message` is a single\nstring; it is meant for logs, so branch on the HTTP status rather than on its text.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong.","example":"OrderId 7c1f4d2e-3b8a-4f6c-9d1e-2a5b8c7d9e01 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message","error"],"type":"object"}}},"description":"There is no active version of the loan contract to render."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Render a pre-contract preview for a loan order","tags":["Loan"],"x-product":{"wallet":"Loan"}}},"/v1/misc/country/{countryISOCode}/region":{"get":{"description":"Returns the first-level subdivisions of a country, such as states or autonomous\ncommunities, sorted by `name`. Codes follow [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2)\nwithout the country prefix: Andalusia is `AN`, not `ES-AN`.\n\nRegion entries carry `iso`, `name` and `fips`. They do **not** include `iso3`, which\nappears only on the country list returned by `GET /v1/misc/country`.\n\nA well-formed code with no data returns `200` with an empty array, not `404`. Curaçao\n(`CW`), Kosovo (`XK`) and Gibraltar (`GI`) return a single entry for the territory itself,\nwith the country code as `iso` and `fips` `00`.\n\nNo authentication is required.\n","parameters":[{"description":"ISO 3166-1 alpha-2 country code, in uppercase.","example":"ES","in":"path","name":"countryISOCode","required":true,"schema":{"pattern":"^[A-Z]{2}$","type":"string"}},{"description":"Language of `name`. `EN` and `ES` are accepted in any case; `en-US` and `en-GB` map to\nEnglish, `es-ES` and `es-AR` to Spanish, and `pt`, `pt-PT` and `pt-BR` to Portuguese.\n`it` and `fr` are also accepted. Any other value falls back to English.\n","example":"ES","in":"query","name":"langCode","schema":{"default":"EN","type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"spain":{"summary":"Spanish autonomous communities","value":[{"fips":"51","iso":"AN","name":"Andalusia"},{"fips":"52","iso":"AR","name":"Aragon"}]},"unknownCountry":{"summary":"Well-formed code with no data","value":[]}},"schema":{"items":{"properties":{"fips":{"description":"Federal Information Processing Standard code for the subdivision.","example":"51","type":"string"},"iso":{"description":"ISO 3166-2 subdivision code without the country prefix.","example":"AN","type":"string"},"name":{"example":"Andalusia","type":"string"}},"required":["iso","name","fips"],"type":"object"},"type":"array"}}},"description":"Regions of the requested country. Empty when there are none."},"400":{"content":{"application/json":{"examples":{"invalidCountryCode":{"value":{"error":"Bad Request","message":["invalid countryISOCode. It should be a ISO 3166 Alpha-2 (ex: ES, AD)"],"statusCode":400}}},"schema":{"description":"Returned with `400` when the request is rejected field by field rather than against the\npublished contract. It is not the same shape as the contract validation error, and the\ndifference that catches integrators out is that **`message` is an array of strings here**,\nwhile everywhere else it is a single string.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"One human-readable sentence per failed constraint.","example":["iban should not be empty","iban must be a string"],"items":{"type":"string"},"type":"array"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["message","error","statusCode"],"type":"object"}}},"description":"`countryISOCode` is not two uppercase letters."}},"summary":"List regions for a country","tags":["Misc"],"x-product":{"wallet":"Misc"}}},"/v1/signin/apikey":{"post":{"description":"Authenticates a user using an API key and returns a JWT access token.\n\nThe API key must be sent via the `ApiKeyAuth` security scheme. The request body\ncarries the `userId` that the key belongs to. On success the response contains an\n`accessToken` with its expiration timestamp.\n","requestBody":{"content":{"application/json":{"example":{"userId":"550e8400-e29b-41d4-a716-446655440000"},"schema":{"properties":{"userId":{"pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}},"required":["userId"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"accessToken":{"expirationTime":1727100000,"token":"header.payload.signature"}},"schema":{"properties":{"accessToken":{"properties":{"expirationTime":{"description":"The expiration time as Unix timestamp","format":"int64","type":"integer"},"token":{"description":"The JWT access token","type":"string"}},"required":["token","expirationTime"],"type":"object"}},"required":["accessToken"],"type":"object"}}},"description":"Authentication successful."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials — API key not valid or does not belong to the user."},"404":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"User not found."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"ApiKeyAuth":[]}],"summary":"Sign in with API key","tags":["Auth"],"x-product":{"embed":"Auth flow","spot":"WsAuth","wallet":"Access"}}},"/v1/signin/embed":{"post":{"description":"Authenticates a user with an embed access token. Returns a JWT access token, a refresh\ntoken, and a session object.\n\nWhen the subaccount's main user has `forceSubaccountSfa` enabled, the caller must\nsupply a TOTP code via the `x-totp` and `x-totp-type` headers. If the code is missing\nor the main user requires SFA, the gateway returns `428` with the SFA metadata needed\nto prompt the user; if the code is wrong, `420` is returned.\n","parameters":[{"description":"TOTP code required when the main account has `forceSubaccountSfa` enabled.","in":"header","name":"x-totp","schema":{"description":"4-6 digit TOTP verification code","example":"123456","pattern":"^[0-9]{4,6}$","type":"string"}},{"description":"TOTP delivery method (e.g. `gauth`, `email`, `sms`).","in":"header","name":"x-totp-type","schema":{"default":"gauth","description":"The type of TOTP verification method","enum":["gauth","email","sms","call","whatsapp"],"type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"accessToken":"header.payload.signature"},"schema":{"properties":{"accessToken":{"description":"The embed access token provided by the integrator.","type":"string"}},"required":["accessToken"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"accessToken":{"expirationTime":1727100000,"token":"header.payload.signature"},"refreshToken":{"expirationTime":1727186400,"token":"header.payload.signature"},"session":{"expirationTime":1727186400,"id":"550e8400-e29b-41d4-a716-446655440099"}},"schema":{"properties":{"accessToken":{"properties":{"expirationTime":{"description":"The expiration time as Unix timestamp","format":"int64","type":"integer"},"token":{"description":"The JWT access token","type":"string"}},"required":["token","expirationTime"],"type":"object"},"refreshToken":{"properties":{"expirationTime":{"description":"The expiration time as Unix timestamp","format":"int64","type":"integer"},"token":{"description":"The JWT access token","type":"string"}},"required":["token","expirationTime"],"type":"object"},"session":{"properties":{"expirationTime":{"type":"integer"},"id":{"pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}},"required":["id","expirationTime"],"type":"object"}},"required":["accessToken","refreshToken","session"],"type":"object"}}},"description":"Authentication successful."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials — embed token not valid."},"420":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Two-factor authentication code not valid."},"428":{"content":{"application/json":{"example":{"data":{"availableChannels":["sms","whatsapp"],"defaultChannel":"sms","sfaProcessInitialized":false,"sfaType":"gauth"},"error":"Precondition Required","message":"sfa required","statusCode":428},"schema":{"allOf":[{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"},{"properties":{"data":{"allOf":[{"properties":{"availableChannels":{"description":"Phone OTP channels available for the current user","items":{"enum":["sms","call","whatsapp"],"type":"string"},"type":"array"},"defaultChannel":{"enum":["sms","call","whatsapp"],"type":"string"}},"type":"object"},{"properties":{"retryIntervalSeconds":{"type":"integer"},"sfaProcessInitialized":{"type":"boolean"},"sfaType":{"enum":["gauth","sms","email","call","whatsapp"],"type":"string"}},"type":"object"}]}},"type":"object"}]}}},"description":"Two-factor authentication required. The response includes SFA metadata\n(`sfaType`, `sfaProcessInitialized`, `availableChannels`, `defaultChannel`,\n`retryIntervalSeconds`) inside `data`.\n"},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"summary":"Sign in with embed token","tags":["Auth"],"x-product":{"wallet":"Access"}}},"/v1/social-pay/order":{"get":{"description":"Returns all social payment orders for the authenticated user, including both sent\nand received orders with their current status and status history.\n","responses":{"200":{"content":{"application/json":{"schema":{"items":{"properties":{"amount":{"example":"0.01","type":"string"},"concept":{"example":"A concept of pay","type":"string"},"createdAt":{"example":"2024-01-01T00:00:00.000Z","format":"date-time","type":"string"},"currency":{"example":"BTC","type":"string"},"email":{"example":"user@example.com","type":"string"},"expiryDate":{"example":"2024-01-08T00:00:00.000Z","format":"date-time","type":"string"},"note":{"example":"A note in the pay","type":"string"},"orderId":{"example":"304809b8-0a04-4f88-af75-069ab4e5a36b","format":"uuid","type":"string"},"phone":{"properties":{"countryCode":{"example":"34","pattern":"^[0-9]{1,4}$","type":"string"},"number":{"example":"666111333","maxLength":32,"pattern":"^[0-9]+$","type":"string"}},"required":["number","countryCode"],"type":"object"},"pocketId":{"example":"e108f9c3-c3ae-4c43-b2fb-7ac04c2f12f6","format":"uuid","type":"string"},"senderName":{"example":"Satoshi Nakamoto","type":"string"},"status":{"enum":["waiting-funds","pending","accepted","cancelled","expired","error"],"example":"accepted","type":"string"},"statusChanges":{"items":{"properties":{"author":{"example":"965d26e4-6447-4dc0-a510-72bcca37f510","format":"uuid","type":"string"},"created":{"example":"2024-01-01T00:00:00.000Z","format":"date-time","type":"string"},"newStatus":{"enum":["waiting-funds","pending","accepted","cancelled","expired","error"],"example":"waiting-funds","type":"string"},"reason":{"example":"Order created","type":"string"}},"required":["newStatus","author","created","reason"],"type":"object"},"type":"array"},"type":{"enum":["email","phone","alias"],"example":"email","type":"string"},"userId":{"example":"cb3795e1-8a1f-47e4-a9ce-d42a1a31785a","format":"uuid","type":"string"},"walletMovementId":{"example":"965d26e4-6447-4dc0-a510-72bcca37f510","format":"uuid","type":"string"}},"required":["createdAt","expiryDate","orderId","type","status","userId","pocketId","currency","amount","walletMovementId","statusChanges","senderName"],"type":"object"},"type":"array"}}},"description":"List of social pay orders."},"400":{"content":{"application/json":{"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"Bad request."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"412":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"User not found."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"List social pay orders","tags":["Pay"],"x-product":{"wallet":"Transfers"}},"post":{"deprecated":true,"description":"Deprecated — use POST /v2/social-pay/order instead.\nCreates a new social payment order. The recipient is identified by email, phone, or\nalias depending on the `type` field. The amount is debited from the sender's pocket.\n\nThis endpoint requires two-factor authentication — the TOTP code is sent via the\n`x-totp` and `x-totp-type` headers.\nWhen TOTP is missing, this version maps the upstream HTTP 428 to HTTP 420 so existing clients keep the legacy contract. TOTP mismatch also returns HTTP 420.\n","parameters":[{"description":"TOTP verification code","in":"header","name":"x-totp","schema":{"description":"4-6 digit TOTP verification code","example":"123456","pattern":"^[0-9]{4,6}$","type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"amount":"10.00","currency":"EUR","email":"recipient@example.com","note":"Happy birthday!","pocketId":"e108f9c3-c3ae-4c43-b2fb-7ac04c2f12f6","type":"email"},"schema":{"properties":{"alias":{"type":"string"},"amount":{"example":"0.01","maxLength":50,"minLength":1,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"currency":{"example":"BTC","type":"string"},"email":{"example":"user@example.com","format":"email","maxLength":96,"minLength":6,"type":"string"},"note":{"type":"string"},"phone":{"properties":{"countryCode":{"example":"34","pattern":"^[0-9]{1,4}$","type":"string"},"number":{"example":"666111333","maxLength":32,"pattern":"^[0-9]+$","type":"string"}},"required":["number","countryCode"],"type":"object"},"pocketId":{"example":"e108f9c3-c3ae-4c43-b2fb-7ac04c2f12f6","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"},"type":{"enum":["email","phone","alias"],"example":"email","type":"string"}},"required":["pocketId","type","amount","currency"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"amount":{"example":"0.01","type":"string"},"concept":{"example":"A concept of pay","type":"string"},"createdAt":{"example":"2024-01-01T00:00:00.000Z","format":"date-time","type":"string"},"currency":{"example":"BTC","type":"string"},"email":{"example":"user@example.com","type":"string"},"expiryDate":{"example":"2024-01-08T00:00:00.000Z","format":"date-time","type":"string"},"note":{"example":"A note in the pay","type":"string"},"orderId":{"example":"304809b8-0a04-4f88-af75-069ab4e5a36b","format":"uuid","type":"string"},"phone":{"properties":{"countryCode":{"example":"34","pattern":"^[0-9]{1,4}$","type":"string"},"number":{"example":"666111333","maxLength":32,"pattern":"^[0-9]+$","type":"string"}},"required":["number","countryCode"],"type":"object"},"pocketId":{"example":"e108f9c3-c3ae-4c43-b2fb-7ac04c2f12f6","format":"uuid","type":"string"},"senderName":{"example":"Satoshi Nakamoto","type":"string"},"status":{"enum":["waiting-funds","pending","accepted","cancelled","expired","error"],"example":"accepted","type":"string"},"statusChanges":{"items":{"properties":{"author":{"example":"965d26e4-6447-4dc0-a510-72bcca37f510","format":"uuid","type":"string"},"created":{"example":"2024-01-01T00:00:00.000Z","format":"date-time","type":"string"},"newStatus":{"enum":["waiting-funds","pending","accepted","cancelled","expired","error"],"example":"waiting-funds","type":"string"},"reason":{"example":"Order created","type":"string"}},"required":["newStatus","author","created","reason"],"type":"object"},"type":"array"},"type":{"enum":["email","phone","alias"],"example":"email","type":"string"},"userId":{"example":"cb3795e1-8a1f-47e4-a9ce-d42a1a31785a","format":"uuid","type":"string"},"walletMovementId":{"example":"965d26e4-6447-4dc0-a510-72bcca37f510","format":"uuid","type":"string"}},"required":["createdAt","expiryDate","orderId","type","status","userId","pocketId","currency","amount","walletMovementId","statusChanges","senderName"],"type":"object"}}},"description":"Order created."},"400":{"content":{"application/json":{"schema":{"properties":{"error":{"example":"Bad Request","type":"string"},"message":{"oneOf":[{"example":"pocketId must be a UUID","type":"string"},{"example":["pocketId must be a UUID","type must be one of the following values: email, phone, alias"],"items":{"type":"string"},"type":"array"}]},"statusCode":{"example":400,"type":"number"}},"required":["message","error","statusCode"],"type":"object"}}},"description":"Validation error."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"412":{"content":{"application/json":{"schema":{"properties":{"error":{"example":"Precondition Failed","type":"string"},"message":{"oneOf":[{"example":"User not found","type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"example":412,"type":"number"}},"required":["message","error","statusCode"],"type":"object"}}},"description":"User not valid or not found."},"420":{"content":{"application/json":{"schema":{"oneOf":[{"properties":{"message":{"example":"2FA TOTP doesn't match","type":"string"},"reqId":{"type":"string"},"statusCode":{"example":420,"type":"number"}},"required":["message"],"type":"object"},{"properties":{"message":{"example":"2FA TOTP is required","type":"string"},"reqId":{"type":"string"},"statusCode":{"example":420,"type":"number"}},"required":["message"],"type":"object"}]}}},"description":"2FA TOTP is required or doesn't match"},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Create social pay order","tags":["Pay"],"x-product":{"wallet":"Transfers"},"x-use":"POST /v2/social-pay/order"}},"/v1/social-pay/order/claim":{"post":{"description":"Claims one or more pending social payment orders for the authenticated user. Each\nclaim specifies the target pocket where the funds should be deposited.\n\nReturns a result per order indicating success or failure with a message.\n","requestBody":{"content":{"application/json":{"example":[{"orderId":"304809b8-0a04-4f88-af75-069ab4e5a36b","pocketId":"e108f9c3-c3ae-4c43-b2fb-7ac04c2f12f6"}],"schema":{"items":{"properties":{"orderId":{"example":"304809b8-0a04-4f88-af75-069ab4e5a36b","format":"uuid","type":"string"},"pocketId":{"example":"e108f9c3-c3ae-4c43-b2fb-7ac04c2f12f6","format":"uuid","type":"string"}},"required":["pocketId","orderId"],"type":"object"},"type":"array"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":[{"orderId":"304809b8-0a04-4f88-af75-069ab4e5a36b","result":true}],"schema":{"items":{"properties":{"message":{"example":"Message to claim payment","type":"string"},"orderId":{"example":"304809b8-0a04-4f88-af75-069ab4e5a36b","format":"uuid","type":"string"},"result":{"example":true,"type":"boolean"}},"required":["orderId","result"],"type":"object"},"type":"array"}}},"description":"Claim results (one per order)."},"400":{"content":{"application/json":{"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"Validation error."},"403":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Invalid credentials, or the user is not allowed to claim orders.\n"},"412":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"User does not meet the requirements to claim:\n`B2M_PAY_VERIFICATION_TIER_COMPLIANCE_LIMITED_REQUIRED`,\n`B2M_PAY_VERIFICATION_SPACE_CENTER_LEVEL_REQUIRED`, or user not valid.\n"},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Claim pending social pay orders","tags":["Pay"],"x-product":{"wallet":"Transfers"}}},"/v1/teller/iban/validate":{"get":{"deprecated":true,"description":"Deprecated — use POST /v1/teller/iban/validate instead. Removal planned for 2027-04-05.\n","parameters":[{"description":"IBAN to check. Spaces are ignored.","example":"ES9121000418450200051332","in":"query","name":"iban","required":true,"schema":{"minLength":1,"type":"string"}},{"description":"Country of the bank account, as an uppercase ISO 3166-1 alpha-2 code. The check only applies\nto SEPA countries: for a country outside SEPA, `result` is `true` without the IBAN being checked.\n","example":"ES","in":"query","name":"countryCode","schema":{"pattern":"^[A-Z]{2}$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"result":true},"schema":{"properties":{"result":{"description":"Whether the IBAN is well formed and its check digits are correct.","example":true,"type":"boolean"}},"required":["result"],"type":"object"}}},"description":"Result of the check."},"400":{"content":{"application/json":{"example":{"error":"Bad Request","message":["countryCode must be a valid ISO31661 Alpha2 code"],"statusCode":400},"schema":{"description":"Returned with `400` when the request is rejected field by field rather than against the\npublished contract. It is not the same shape as the contract validation error, and the\ndifference that catches integrators out is that **`message` is an array of strings here**,\nwhile everywhere else it is a single string.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"One human-readable sentence per failed constraint.","example":["iban should not be empty","iban must be a string"],"items":{"type":"string"},"type":"array"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["message","error","statusCode"],"type":"object"}}},"description":"`iban` is missing or empty, or `countryCode` is not an uppercase ISO 3166-1 alpha-2 code."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Deprecated, use POST /v1/teller/iban/validate instead","tags":["Teller"],"x-product":{"wallet":"Funding"},"x-use":"POST /v1/teller/iban/validate"},"post":{"description":"Checks whether an IBAN is well formed and its check digits are correct. It does not check that the\naccount exists or who holds it.\n\nSend `iban` (required) and `countryCode` (optional) in the JSON body. This operation does not\naccept query parameters. An invalid IBAN is not an error: the response is `200` with\n`result: false`.\n","requestBody":{"content":{"application/json":{"example":{"countryCode":"ES","iban":"ES91 2100 0418 4502 0005 1332"},"schema":{"properties":{"countryCode":{"description":"Country of the bank account, as an uppercase ISO 3166-1 alpha-2 code. The check only applies\nto SEPA countries: for a country outside SEPA, `result` is `true` without the IBAN being checked.\n","example":"ES","pattern":"^[A-Z]{2}$","type":"string"},"iban":{"description":"IBAN to check. Spaces are ignored, so both the electronic and the printed format are accepted.","example":"ES9121000418450200051332","minLength":1,"type":"string"}},"required":["iban"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"examples":{"invalid":{"summary":"Wrong check digits","value":{"result":false}},"valid":{"summary":"Valid IBAN","value":{"result":true}}},"schema":{"properties":{"result":{"description":"Whether the IBAN is well formed and its check digits are correct.","example":true,"type":"boolean"}},"required":["result"],"type":"object"}}},"description":"Result of the check."},"400":{"content":{"application/json":{"example":{"error":"Bad Request","message":["iban should not be empty","iban must be a string"],"statusCode":400},"schema":{"description":"Returned with `400` when the request is rejected field by field rather than against the\npublished contract. It is not the same shape as the contract validation error, and the\ndifference that catches integrators out is that **`message` is an array of strings here**,\nwhile everywhere else it is a single string.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"One human-readable sentence per failed constraint.","example":["iban should not be empty","iban must be a string"],"items":{"type":"string"},"type":"array"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["message","error","statusCode"],"type":"object"}}},"description":"`iban` is missing or empty, or `countryCode` is not an uppercase ISO 3166-1 alpha-2 code."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Check if iban is valid","tags":["Teller"],"x-product":{"wallet":"Funding"}}},"/v1/teller/order":{"post":{"description":"Executes an order previously created with `POST /v1/teller/order/proforma`, charging it with the\npayment method chosen there. A proforma can be executed only once and only while it is valid, so\nan expired one has to be created again.\n\nWhen the user has to complete the payment, for example to pass 3-D Secure on a card or to approve\na Bizum payment, the response comes with `status: waiting-user` and `provider.requestConfiguration`\nsays how: open its `uri` when `type` is `iframe`, or wait for the user to approve it outside the\napp when `type` is `external`.\n","requestBody":{"content":{"application/json":{"example":{"orderId":"dfcf2797-05f2-4cbb-ae5b-f5608dbbf6a9"},"schema":{"properties":{"orderId":{"description":"`orderId` returned by `POST /v1/teller/order/proforma`. A proforma can be executed only once.\n","example":"dfcf2797-05f2-4cbb-ae5b-f5608dbbf6a9","format":"uuid","type":"string"},"params":{"description":"Parameters that depend on the payment method of the proforma.","properties":{"paypal":{"description":"Parameters for orders paid with PayPal.","properties":{"clientMetadataId":{"description":"Client metadata ID generated by the PayPal SDK on the user's device.","example":"example-client-metadata-id","type":"string"}},"required":["clientMetadataId"],"type":"object"}},"type":"object"}},"required":["orderId"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"examples":{"accepted":{"summary":"Payment completed without user action","value":{"orderId":"dfcf2797-05f2-4cbb-ae5b-f5608dbbf6a9","status":"accepted"}},"external":{"summary":"Bizum payment awaiting approval in the banking app","value":{"orderId":"dfcf2797-05f2-4cbb-ae5b-f5608dbbf6a9","provider":{"requestConfiguration":{"type":"external"}},"status":"waiting-user","token":"7w5gw7bw35gpb5hpgw6ph"}},"iframe":{"summary":"Card payment awaiting 3-D Secure","value":{"orderId":"dfcf2797-05f2-4cbb-ae5b-f5608dbbf6a9","provider":{"requestConfiguration":{"type":"iframe","uri":"https://payments.example.com/payment/tokenized/7w5gw7bw35gpb5hpgw6ph"}},"status":"waiting-user","token":"7w5gw7bw35gpb5hpgw6ph"}}},"schema":{"properties":{"orderId":{"description":"ID of the order, the same as the proforma's.","example":"dfcf2797-05f2-4cbb-ae5b-f5608dbbf6a9","format":"uuid","type":"string"},"provider":{"description":"How the user completes the payment. Only present when `status` is `waiting-user`.","properties":{"requestConfiguration":{"description":"What the client has to do so the user can complete the payment.","properties":{"type":{"description":"* `iframe`: open `uri` (in a web view or an iframe) so the user can authorise the payment.\n* `external`: the user authorises the payment outside the app, for example in their\n  banking app; there is no `uri`.\n","enum":["iframe","external"],"example":"iframe","type":"string"},"uri":{"description":"Payment page to open. Only present when `type` is `iframe`.","example":"https://payments.example.com/payment/tokenized/7w5gw7bw35gpb5hpgw6ph","format":"uri","type":"string"}},"required":["type"],"type":"object"}},"required":["requestConfiguration"],"type":"object"},"status":{"description":"Status of the order after the request. With `waiting-user` the user still has to complete the\npayment as described in `provider.requestConfiguration`; the final outcome can be followed with\n`GET /v1/teller/order/status`.\n","enum":["pending","waiting-user","rejected","accepted"],"example":"waiting-user","type":"string"},"token":{"description":"Token of the payment session. Only present when `status` is `waiting-user`.","example":"7w5gw7bw35gpb5hpgw6ph","type":"string"}},"required":["orderId","status"],"type":"object"}}},"description":"Order executed. Check `status` to know whether the user still has to act."},"400":{"content":{"application/json":{"examples":{"alreadyExecuted":{"summary":"The order is no longer pending","value":{"data":{"data":{},"error":"Bad Request","message":"Order status should be pending but it's accepted","statusCode":400},"error":"Bad Request","message":"Order status should be pending but it's accepted","statusCode":400}},"proformaNotFound":{"summary":"The proforma does not exist or has expired","value":{"data":{"data":{},"error":"Bad Request","message":"Order (orderId:dfcf2797-05f2-4cbb-ae5b-f5608dbbf6a9) not found","statusCode":400},"error":"Bad Request","message":"Order (orderId:dfcf2797-05f2-4cbb-ae5b-f5608dbbf6a9) not found","statusCode":400}},"validation":{"summary":"`orderId` is not a UUID","value":{"errors":[{"code":"INVALID_REQUEST_PARAMETER","errors":[{"code":"PATTERN","message":"String does not match pattern ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$: not-a-uuid","params":["^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$","not-a-uuid"],"path":["orderId"]}],"in":"body","message":"Invalid parameter (data): Value failed JSON Schema validation","name":"data","path":["paths","/v1/order","post","parameters","0"]}],"message":"Validation errors"}}},"schema":{"oneOf":[{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"},{"description":"Business error returned by the operation. `statusCode`, `error` and `message` are repeated at the\ntop level and inside `data`, which also carries the error detail in `data.data`.\n","properties":{"data":{"description":"Business error returned by the operation.","properties":{"data":{"additionalProperties":true,"description":"Additional detail about the error. An empty object when there is none.","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Precondition Failed","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Could not find pocket b7e3f8a9-4c1d-4e2f-8a3c-5d6e7f8a9b0c associated to user ac859110-e934-42d8-8643-a7e2de42349c","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":412,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"pocketId is mandatory for deposits","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"}]}}},"description":"The request is malformed, or the proforma cannot be executed: it does not exist, it has\nexpired, it was already executed, or its payment method cannot be executed here. Malformed\nrequests use the `RequestValidationErrorResponse` shape and the rest use\n`TellerWrappedErrorResponse`.\n"},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"example":{"data":{"data":{},"error":"Not Found","message":"Card with id c4d5e658-688b-4eab-b6c0-02ed3318f560 not found","statusCode":404},"error":"Not Found","message":"Card with id c4d5e658-688b-4eab-b6c0-02ed3318f560 not found","statusCode":404},"schema":{"description":"Business error returned by the operation. `statusCode`, `error` and `message` are repeated at the\ntop level and inside `data`, which also carries the error detail in `data.data`.\n","properties":{"data":{"description":"Business error returned by the operation.","properties":{"data":{"additionalProperties":true,"description":"Additional detail about the error. An empty object when there is none.","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Precondition Failed","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Could not find pocket b7e3f8a9-4c1d-4e2f-8a3c-5d6e7f8a9b0c associated to user ac859110-e934-42d8-8643-a7e2de42349c","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":412,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"pocketId is mandatory for deposits","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"}}},"description":"The card or the PayPal account chosen in the proforma is no longer available."},"412":{"content":{"application/json":{"example":{"data":{"data":{},"error":"Precondition Failed","message":"Invalid credit card: c4d5e658-688b-4eab-b6c0-02ed3318f560","statusCode":412},"error":"Precondition Failed","message":"Invalid credit card: c4d5e658-688b-4eab-b6c0-02ed3318f560","statusCode":412},"schema":{"description":"Business error returned by the operation. `statusCode`, `error` and `message` are repeated at the\ntop level and inside `data`, which also carries the error detail in `data.data`.\n","properties":{"data":{"description":"Business error returned by the operation.","properties":{"data":{"additionalProperties":true,"description":"Additional detail about the error. An empty object when there is none.","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Precondition Failed","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Could not find pocket b7e3f8a9-4c1d-4e2f-8a3c-5d6e7f8a9b0c associated to user ac859110-e934-42d8-8643-a7e2de42349c","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":412,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"pocketId is mandatory for deposits","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"}}},"description":"The payment method cannot be charged: the card is no longer valid, or a phone number is\nmissing from the user's profile for a Bizum or MB WAY payment.\n"},"428":{"content":{"application/json":{"example":{"data":{"data":{},"error":"Precondition Required","message":"Low verification tier","statusCode":428},"error":"Precondition Required","message":"Low verification tier","statusCode":428},"schema":{"description":"Business error returned by the operation. `statusCode`, `error` and `message` are repeated at the\ntop level and inside `data`, which also carries the error detail in `data.data`.\n","properties":{"data":{"description":"Business error returned by the operation.","properties":{"data":{"additionalProperties":true,"description":"Additional detail about the error. An empty object when there is none.","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Precondition Failed","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Could not find pocket b7e3f8a9-4c1d-4e2f-8a3c-5d6e7f8a9b0c associated to user ac859110-e934-42d8-8643-a7e2de42349c","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":412,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"pocketId is mandatory for deposits","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"}}},"description":"The user has not completed the identity verification required to pay."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Execute an order","tags":["Teller"],"x-product":{"wallet":"Funding"}}},"/v1/teller/order/cancel":{"post":{"description":"Changes an order status from `waiting-user` to `cancelled`. Use this when the\nuser decides not to proceed with a card payment that is awaiting confirmation.\n","requestBody":{"content":{"application/json":{"example":{"description":"User requested cancellation","orderId":"dfcf2797-05f2-4cbb-ae5b-f5608dbbf6a9"},"schema":{"properties":{"description":{"description":"Reason for the cancellation, as free text.","example":"User requested cancellation","type":"string"},"orderId":{"description":"ID of the order to cancel. Only card orders in status `waiting-user` can be cancelled.","example":"dfcf2797-05f2-4cbb-ae5b-f5608dbbf6a9","format":"uuid","type":"string"}},"required":["orderId","description"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"orderId":"dfcf2797-05f2-4cbb-ae5b-f5608dbbf6a9","status":"cancelled"},"schema":{"properties":{"orderId":{"description":"ID of the cancelled order.","example":"dfcf2797-05f2-4cbb-ae5b-f5608dbbf6a9","format":"uuid","type":"string"},"status":{"description":"New status of the order. Always `cancelled`.","enum":["cancelled"],"example":"cancelled","type":"string"}},"required":["orderId","status"],"type":"object"}}},"description":"Order cancelled."},"400":{"content":{"application/json":{"example":{"errors":[{"code":"INVALID_REQUEST_PARAMETER","errors":[{"code":"OBJECT_MISSING_REQUIRED_PROPERTY","message":"Missing required property: description","params":["description"],"path":[]}],"in":"body","message":"Invalid parameter (data): Value failed JSON Schema validation","name":"data","path":["paths","/v1/order/cancel","post","parameters","0"]}],"message":"Validation errors"},"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"`orderId` or `description` is missing, or `orderId` is not a UUID."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"412":{"content":{"application/json":{"example":{"data":{"data":{},"error":"Precondition Failed","message":"Order 'dfcf2797-05f2-4cbb-ae5b-f5608dbbf6a9' not found","statusCode":412},"error":"Precondition Failed","message":"Order 'dfcf2797-05f2-4cbb-ae5b-f5608dbbf6a9' not found","statusCode":412},"schema":{"description":"Business error returned by the operation. `statusCode`, `error` and `message` are repeated at the\ntop level and inside `data`, which also carries the error detail in `data.data`.\n","properties":{"data":{"description":"Business error returned by the operation.","properties":{"data":{"additionalProperties":true,"description":"Additional detail about the error. An empty object when there is none.","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Precondition Failed","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Could not find pocket b7e3f8a9-4c1d-4e2f-8a3c-5d6e7f8a9b0c associated to user ac859110-e934-42d8-8643-a7e2de42349c","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":412,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"pocketId is mandatory for deposits","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"}}},"description":"The order cannot be cancelled: it does not exist, it is not a card order, or its status is no\nlonger `waiting-user`.\n"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Cancel an order","tags":["Teller"],"x-product":{"wallet":"Funding"}}},"/v1/teller/order/proforma":{"post":{"description":"Creates an order proforma: it prices the order, with its fees and any discount, without charging\nanything. Show the breakdown to the user and, if they accept, execute it with\n`POST /v1/teller/order` and the returned `orderId`.\n\nA proforma is valid for a limited time and can be executed only once. To refresh the price,\ncreate a new one.\n","requestBody":{"content":{"application/json":{"examples":{"bizum":{"summary":"Bizum deposit","value":{"amount":"50","currency":"EUR","destination":{"type":"pocket","value":"eb775a29-365d-4881-b7b9-1fa66fe1eb4d"},"method":{"type":"bizum"},"orderType":"deposit"}},"card":{"summary":"Card deposit into a EUR pocket","value":{"amount":"100","currency":"EUR","destination":{"type":"pocket","value":"eb775a29-365d-4881-b7b9-1fa66fe1eb4d"},"feeType":"SEA","method":{"params":{"cardId":"c4d5e658-688b-4eab-b6c0-02ed3318f560"},"type":"creditcard"},"orderType":"deposit"}}},"schema":{"properties":{"amount":{"description":"Amount to pay, as a decimal string in `currency`.","example":"100","type":"string"},"currency":{"description":"Fiat currency of `amount`, as an ISO 4217 code. When it is not the currency the order is\ncharged in, `amount` is converted at the current rate and `denomination` in the response\nshows the conversion.\n","example":"EUR","pattern":"^[A-Z]{3}$","type":"string"},"description":{"description":"Free text describing the order. Defaults to `Payment with \u003ccurrency\u003e`.","example":"Top-up for savings","type":"string"},"destination":{"description":"Where the funds go. Required when `orderType` is `deposit`.","properties":{"type":{"description":"Kind of destination. Only pockets are supported.","enum":["pocket"],"example":"pocket","type":"string"},"value":{"description":"ID of the destination pocket. It must be a EUR pocket of the user.","example":"eb775a29-365d-4881-b7b9-1fa66fe1eb4d","format":"uuid","type":"string"}},"required":["type","value"],"type":"object"},"feeType":{"description":"Which side of the order `amount` refers to. Defaults to `SEA`.\n * `SEA` (Send Exact Amount): `amount` is what is charged, and fees are taken from it.\n * `REA` (Receive Exact Amount): `amount` is what is received, and fees are added on top.\n","enum":["SEA","REA"],"example":"SEA","type":"string"},"method":{"description":"How the order is paid.","properties":{"params":{"description":"Parameters that depend on `method.type`.","properties":{"cardId":{"description":"ID of one of the user's saved cards, which is the card charged. Required when\n`method.type` is `creditcard`.\n","example":"c4d5e658-688b-4eab-b6c0-02ed3318f560","format":"uuid","type":"string"},"paypalId":{"description":"ID of one of the user's linked PayPal accounts, which is the one charged. Only for\n`paypal`. Omit it to link a new PayPal account, which is rejected if the user already\nhas one.\n","example":"c9c5a4de-3edd-4950-912c-1894a433b36b","format":"uuid","type":"string"}},"type":"object"},"type":{"description":"Payment method. Each one is only available where it is offered to the user.","enum":["creditcard","google-pay","apple-pay","hub-latam","paypal","mbway","bizum"],"example":"creditcard","type":"string"}},"required":["type"],"type":"object"},"orderType":{"description":"Purpose of the order. A `deposit` adds the funds to the pocket in `destination`.","enum":["deposit","purchase"],"example":"deposit","type":"string"}},"required":["amount","currency","orderType","method"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"amountAfterFee":"98.12500000","amountBeforeFee":"100.00000000","benefit":{"amount":"0.62500000","currency":"EUR","levelId":"c1886992-5e48-4d8c-8296-a5d89f2f04cf","percentage":25,"tier":4},"currency":"EUR","denomination":{"amount":"100.00000000","currency":"EUR","rate":{"pair":{"base":"EUR","quote":"EUR"},"value":"1.00000000"}},"fixedFee":"0.30000000","orderId":"dfcf2797-05f2-4cbb-ae5b-f5608dbbf6a9","variableFee":"2.20000000","variableFeePercentage":"0.0220"},"schema":{"properties":{"amountAfterFee":{"description":"Order amount once fees and `benefit` are applied, with 8 decimals. With `feeType` `SEA` it is\nwhat the destination receives; with `REA` it is what is charged.\n","example":"97.50000000","pattern":"^[0-9]+\\.[0-9]{8}$","type":"string"},"amountBeforeFee":{"description":"Order amount before fees, with 8 decimals.","example":"100.00000000","pattern":"^[0-9]+\\.[0-9]{8}$","type":"string"},"benefit":{"description":"Fee discount the user gets from their membership level. It is already applied in\n`amountAfterFee`. Absent when no discount applies.\n","properties":{"amount":{"description":"Amount of the discount, with 8 decimals.","example":"0.62500000","pattern":"^[0-9]+\\.[0-9]{8}$","type":"string"},"currency":{"description":"Currency of `amount`.","example":"EUR","pattern":"^[A-Z]{3}$","type":"string"},"levelId":{"description":"ID of the membership level that grants the discount.","example":"c1886992-5e48-4d8c-8296-a5d89f2f04cf","format":"uuid","type":"string"},"percentage":{"description":"Share of the fee that is discounted, as a percentage.","example":25,"type":"number"},"tier":{"description":"Membership tier of the user that grants the discount.","example":4,"type":"number"}},"required":["amount","currency","percentage","tier"],"type":"object"},"currency":{"description":"Currency the order is charged in. Every amount below is in this currency.","example":"EUR","pattern":"^[A-Z]{3}$","type":"string"},"denomination":{"description":"The amount as requested, and the rate used to convert it to `currency`.","properties":{"amount":{"description":"The requested `amount`, with 8 decimals.","example":"100.00000000","pattern":"^[0-9]+\\.[0-9]{8}$","type":"string"},"currency":{"description":"The requested `currency`.","example":"EUR","pattern":"^[A-Z]{3}$","type":"string"},"rate":{"description":"Conversion rate applied. It is `1` when both currencies are the same.","properties":{"pair":{"description":"Currencies the rate converts between.","properties":{"base":{"description":"Currency the rate converts from; the requested `currency`.","example":"EUR","pattern":"^[A-Z]{3}$","type":"string"},"quote":{"description":"Currency the rate converts to; the currency the order is charged in.","example":"EUR","pattern":"^[A-Z]{3}$","type":"string"}},"required":["base","quote"],"type":"object"},"value":{"description":"Units of `pair.quote` per unit of `pair.base`, with 8 decimals.","example":"1.00000000","pattern":"^[0-9]+\\.[0-9]{8}$","type":"string"}},"required":["value","pair"],"type":"object"}},"required":["amount","currency","rate"],"type":"object"},"fixedFee":{"description":"Flat part of the fee, with 8 decimals.","example":"0.30000000","pattern":"^[0-9]+\\.[0-9]{8}$","type":"string"},"orderId":{"description":"ID of the proforma. Send it to `POST /v1/teller/order` to execute the order.","example":"dfcf2797-05f2-4cbb-ae5b-f5608dbbf6a9","format":"uuid","type":"string"},"variableFee":{"description":"Part of the fee proportional to the amount, with 8 decimals.","example":"2.20000000","pattern":"^[0-9]+\\.[0-9]{8}$","type":"string"},"variableFeePercentage":{"description":"Rate of the proportional fee as a fraction with 4 decimals, so `0.0220` means 2.2 %.","example":"0.0220","pattern":"^[0-9]+\\.[0-9]{4}$","type":"string"}},"required":["orderId","denomination","currency","amountBeforeFee","amountAfterFee","fixedFee","variableFee","variableFeePercentage"],"type":"object"}}},"description":"Proforma with the fee breakdown."},"400":{"content":{"application/json":{"examples":{"missingDestination":{"summary":"Deposit without a destination pocket","value":{"data":{"data":{},"error":"Bad Request","message":"pocketId is mandatory for deposits","statusCode":400},"error":"Bad Request","message":"pocketId is mandatory for deposits","statusCode":400}},"validation":{"summary":"`method.type` outside the allowed values","value":{"errors":[{"code":"INVALID_REQUEST_PARAMETER","errors":[{"code":"ENUM_MISMATCH","message":"No enum match for: transfer","params":["transfer"],"path":["method","type"]}],"in":"body","message":"Invalid parameter (data): Value failed JSON Schema validation","name":"data","path":["paths","/v1/order/proforma","post","parameters","0"]}],"message":"Validation errors"}}},"schema":{"oneOf":[{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"},{"description":"Business error returned by the operation. `statusCode`, `error` and `message` are repeated at the\ntop level and inside `data`, which also carries the error detail in `data.data`.\n","properties":{"data":{"description":"Business error returned by the operation.","properties":{"data":{"additionalProperties":true,"description":"Additional detail about the error. An empty object when there is none.","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Precondition Failed","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Could not find pocket b7e3f8a9-4c1d-4e2f-8a3c-5d6e7f8a9b0c associated to user ac859110-e934-42d8-8643-a7e2de42349c","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":412,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"pocketId is mandatory for deposits","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"}]}}},"description":"The request is malformed, or its values do not make a valid order: a deposit without\n`destination`, an unsupported `method.type` or `currency`, or a new PayPal account for a user who\nalready has one. Malformed requests use the `RequestValidationErrorResponse` shape and the rest\nuse `TellerWrappedErrorResponse`.\n"},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"example":{"data":{"data":{},"error":"Not Found","message":"Card with id c4d5e658-688b-4eab-b6c0-02ed3318f560 not found","statusCode":404},"error":"Not Found","message":"Card with id c4d5e658-688b-4eab-b6c0-02ed3318f560 not found","statusCode":404},"schema":{"description":"Business error returned by the operation. `statusCode`, `error` and `message` are repeated at the\ntop level and inside `data`, which also carries the error detail in `data.data`.\n","properties":{"data":{"description":"Business error returned by the operation.","properties":{"data":{"additionalProperties":true,"description":"Additional detail about the error. An empty object when there is none.","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Precondition Failed","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Could not find pocket b7e3f8a9-4c1d-4e2f-8a3c-5d6e7f8a9b0c associated to user ac859110-e934-42d8-8643-a7e2de42349c","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":412,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"pocketId is mandatory for deposits","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"}}},"description":"The card in `method.params.cardId` or the PayPal account in `method.params.paypalId` is not one of the user's."},"406":{"content":{"application/json":{"example":{"data":{"data":{"amountAfterFee":-20000000,"amountBeforeFee":10000000,"currency":"EUR","feeType":"SEA","fixedFee":30000000,"type":"deposit-creditcard","variableFee":0,"variableFeePercentage":0},"error":"Not Acceptable","message":"The amount after fees is negative","statusCode":406},"error":"Not Acceptable","message":"The amount after fees is negative","statusCode":406},"schema":{"description":"Business error returned by the operation. `statusCode`, `error` and `message` are repeated at the\ntop level and inside `data`, which also carries the error detail in `data.data`.\n","properties":{"data":{"description":"Business error returned by the operation.","properties":{"data":{"additionalProperties":true,"description":"Additional detail about the error. An empty object when there is none.","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Precondition Failed","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Could not find pocket b7e3f8a9-4c1d-4e2f-8a3c-5d6e7f8a9b0c associated to user ac859110-e934-42d8-8643-a7e2de42349c","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":412,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"pocketId is mandatory for deposits","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"}}},"description":"The fees are larger than the amount, so nothing would be left. Raise `amount`. `data.data`\ncarries the breakdown that was computed.\n"},"412":{"content":{"application/json":{"example":{"data":{"data":{},"error":"Precondition Failed","message":"Pocket currency \"BTC\" not supported: must be \"EUR\"","statusCode":412},"error":"Precondition Failed","message":"Pocket currency \"BTC\" not supported: must be \"EUR\"","statusCode":412},"schema":{"description":"Business error returned by the operation. `statusCode`, `error` and `message` are repeated at the\ntop level and inside `data`, which also carries the error detail in `data.data`.\n","properties":{"data":{"description":"Business error returned by the operation.","properties":{"data":{"additionalProperties":true,"description":"Additional detail about the error. An empty object when there is none.","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Precondition Failed","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Could not find pocket b7e3f8a9-4c1d-4e2f-8a3c-5d6e7f8a9b0c associated to user ac859110-e934-42d8-8643-a7e2de42349c","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":412,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"pocketId is mandatory for deposits","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"}}},"description":"The order cannot be made for this user or pocket: the destination pocket does not exist, is not\nthe user's or is not in EUR, or the payment method is not available in the user's country.\n"},"417":{"content":{"application/json":{"examples":{"monthAmount":{"summary":"Above what is left of the monthly limit","value":{"data":{"data":{"available":{"amount":"200.00000000","currency":"EUR"},"disposed":{"amount":"4800.00000000","currency":"EUR"},"limit":{"amount":"5000.00000000","currency":"EUR"},"type":"month-amount"},"error":"Expectation Failed","message":"The operation exceeds the max amount allowed per month","statusCode":417},"error":"Expectation Failed","message":"The operation exceeds the max amount allowed per month","statusCode":417}},"shotMax":{"summary":"Above the maximum per order","value":{"data":{"data":{"limit":{"amount":"2000.00000000","currency":"EUR"},"type":"shot-max"},"error":"Expectation Failed","message":"The operation exceeds the max amount per operation","statusCode":417},"error":"Expectation Failed","message":"The operation exceeds the max amount per operation","statusCode":417}}},"schema":{"description":"Returned with `417` when the order is outside the limits of the user. `data.data` says which limit\nwas hit and by how much.\n","properties":{"data":{"description":"The same error, with the detail of the limit in `data`.","properties":{"data":{"description":"The limit that the order hits. When several apply, the most restrictive one is reported.","properties":{"available":{"description":"Amount still available in the period. Only for the `*-amount` types.","properties":{"amount":{"description":"Amount still available.","example":"200.00000000","type":"string"},"currency":{"description":"Currency of `amount`.","example":"EUR","type":"string"}},"type":"object"},"disposed":{"description":"Amount already used in the period. Only for the `*-amount` types.","properties":{"amount":{"description":"Amount already used.","example":"1800.00000000","type":"string"},"currency":{"description":"Currency of `amount`.","example":"EUR","type":"string"}},"type":"object"},"limit":{"description":"Value of the limit. For the `*-quantity` types it is a number of orders and has no `currency`.","properties":{"amount":{"description":"Value of the limit, as an amount or a number of orders.","example":"2000.00000000","oneOf":[{"type":"string"},{"type":"number"}]},"currency":{"description":"Currency of `amount`.","example":"EUR","type":"string"}},"required":["amount"],"type":"object"},"remaining":{"description":"Amount still available at the current verification level. Only for `kyc-limit` and `compliance-limit`.","properties":{"amount":{"description":"Amount still available.","example":"150.00000000","type":"string"},"currency":{"description":"Currency of `amount`.","example":"EUR","type":"string"}},"type":"object"},"type":{"description":"Which limit was hit.\n* `shot-min`, `shot-max`: minimum and maximum amount of a single order.\n* `day-amount`, `week-amount`, `month-amount`, `year-amount`: maximum amount accumulated in the period.\n* `day-quantity`, `week-quantity`, `month-quantity`, `year-quantity`: maximum number of orders in the period.\n* `kyc-limit`, `compliance-limit`: maximum amount allowed by the user's current verification level.\n","enum":["shot-min","shot-max","day-amount","week-amount","month-amount","year-amount","day-quantity","week-quantity","month-quantity","year-quantity","kyc-limit","compliance-limit"],"example":"shot-max","type":"string"}},"required":["type","limit"],"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Expectation Failed","type":"string"},"message":{"description":"Same as the top-level `message`.","example":"The operation exceeds the max amount per operation","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":417,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Expectation Failed","type":"string"},"message":{"description":"Human-readable description of the limit that was hit.","example":"The operation exceeds the max amount per operation","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","enum":[417],"example":417,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"}}},"description":"The order is outside the limits of the user. `data.data` says which limit and by how much."},"428":{"content":{"application/json":{"example":{"data":{"data":{},"error":"Precondition Required","message":"Low verification tier","statusCode":428},"error":"Precondition Required","message":"Low verification tier","statusCode":428},"schema":{"description":"Business error returned by the operation. `statusCode`, `error` and `message` are repeated at the\ntop level and inside `data`, which also carries the error detail in `data.data`.\n","properties":{"data":{"description":"Business error returned by the operation.","properties":{"data":{"additionalProperties":true,"description":"Additional detail about the error. An empty object when there is none.","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Precondition Failed","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Could not find pocket b7e3f8a9-4c1d-4e2f-8a3c-5d6e7f8a9b0c associated to user ac859110-e934-42d8-8643-a7e2de42349c","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":412,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"pocketId is mandatory for deposits","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"}}},"description":"The user has not completed the identity verification required for this order."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Create an order proforma","tags":["Teller"],"x-product":{"wallet":"Funding"}}},"/v1/teller/order/status":{"get":{"description":"Returns the current status of a teller order of the authenticated user, identified by its order ID\nor its wallet proforma ID.\n\nAn ID that does not match any order of the user is not an error: the response is `200` with\n`status: pending`.\n","parameters":[{"description":"The order ID or the wallet proforma ID.","example":"dfcf2797-05f2-4cbb-ae5b-f5608dbbf6a9","in":"query","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"status":"accepted"},"schema":{"properties":{"status":{"description":"Current status of the order. An order that is not found for the user is reported as `pending`,\nso `pending` does not prove that the order exists.\n\n`waiting-user` means the order is waiting for the user to complete the payment, `accepted`\nthat it completed successfully, and `rejected`, `cancelled` and `expired` that it did not.\n","enum":["waiting-user","pending","review","processing","accepted","rejected","refunded","cancelled","expired","withdrawing","wallet-refunded"],"example":"accepted","type":"string"}},"required":["status"],"type":"object"}}},"description":"Order status."},"400":{"content":{"application/json":{"example":{"errors":[{"code":"INVALID_REQUEST_PARAMETER","errors":[{"code":"PATTERN","description":"The order ID or the wallet proforma ID","message":"String does not match pattern ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$: not-a-uuid","params":["^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$","not-a-uuid"],"path":[]}],"in":"query","message":"Invalid parameter (id): Value failed JSON Schema validation","name":"id","path":["paths","/v1/order/status","get","parameters","0"]}],"message":"Validation errors"},"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"`id` is missing or is not a UUID."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get teller order status","tags":["Teller"],"x-product":{"wallet":"Funding"}}},"/v1/teller/pocket/reference":{"get":{"description":"Returns the reference to deposit into a pocket by bank transfer, together with the bank accounts\nthat accept the deposit.\n\nTo fund the pocket, send a transfer to any of the accounts in `bankAccounts` with\n`pocket.reference` as the concept. The reference is assigned the first time it is requested and\nstays the same afterwards.\n","parameters":[{"description":"ID of a pocket of the authenticated user.","example":"b7e3f8a9-4c1d-4e2f-8a3c-5d6e7f8a9b0c","in":"query","name":"pocketId","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"bankAccounts":{"account001":{"account":"ES91 2100 0418 4502 0005 1332","address":"1 Example Street, Madrid, Spain","bankId":"deea5e5c-c27f-4064-ad5b-0ac37dda6699","bankName":"Example Bank","beneficiary":"Bitcoinforme S.L.","public":true,"swift":"EXAMPLESXXX"}},"pocket":{"pocketId":"b7e3f8a9-4c1d-4e2f-8a3c-5d6e7f8a9b0c","reference":"K7Q2MZ9XH4TB","userId":"ac859110-e934-42d8-8643-a7e2de42349c"}},"schema":{"properties":{"bankAccounts":{"additionalProperties":{"description":"A bank account that accepts deposits.","properties":{"account":{"description":"Account number to send the transfer to, usually an IBAN in its printed format.","example":"ES91 2100 0418 4502 0005 1332","type":"string"},"address":{"description":"Postal address of the bank or the beneficiary.","example":"1 Example Street, Madrid, Spain","type":"string"},"bankId":{"description":"ID of the bank account.","example":"deea5e5c-c27f-4064-ad5b-0ac37dda6699","format":"uuid","type":"string"},"bankName":{"description":"Name of the bank.","example":"Example Bank","type":"string"},"beneficiary":{"description":"Account holder to put as the beneficiary of the transfer.","example":"Bitcoinforme S.L.","type":"string"},"public":{"description":"Always `true`, since only accounts open to deposits are returned.","example":true,"type":"boolean"},"swift":{"description":"SWIFT/BIC code of the bank. It is `-` when the account has none.","example":"EXAMPLESXXX","type":"string"}},"required":["bankId","beneficiary","bankName","account"],"type":"object"},"description":"Bank accounts that accept deposits with this reference, keyed by an account identifier. Any of\nthem can be used.\n","example":{"account001":{"account":"ES91 2100 0418 4502 0005 1332","address":"1 Example Street, Madrid, Spain","bankId":"deea5e5c-c27f-4064-ad5b-0ac37dda6699","bankName":"Example Bank","beneficiary":"Bitcoinforme S.L.","public":true,"swift":"EXAMPLESXXX"}},"type":"object"},"pocket":{"description":"The pocket and the reference assigned to it.","properties":{"pocketId":{"description":"ID of the pocket the reference belongs to.","example":"b7e3f8a9-4c1d-4e2f-8a3c-5d6e7f8a9b0c","format":"uuid","type":"string"},"reference":{"description":"Reference to put in the concept of the bank transfer so the deposit is credited to this\npocket. It is permanent: the same pocket always returns the same reference. It has 12\ncharacters and leaves out `I`, `O`, `0` and `1` to avoid confusion when typed by hand.\n","example":"K7Q2MZ9XH4TB","pattern":"^[A-HJ-NP-Z2-9]{12}$","type":"string"},"userId":{"description":"ID of the user who owns the pocket.","example":"ac859110-e934-42d8-8643-a7e2de42349c","format":"uuid","type":"string"}},"required":["userId","pocketId","reference"],"type":"object"}},"required":["pocket","bankAccounts"],"type":"object"}}},"description":"Pocket reference with the bank accounts to transfer to."},"400":{"content":{"application/json":{"example":{"errors":[{"code":"INVALID_REQUEST_PARAMETER","errors":[{"code":"REQUIRED","description":"Id of the pocket to retrieve the reference from","message":"Value is required but was not provided","path":[]}],"in":"query","message":"Invalid parameter (pocketId): Value is required but was not provided","name":"pocketId","path":["paths","/v1/pocket/reference","get","parameters","0"]}],"message":"Validation errors"},"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"`pocketId` is missing or is not a UUID."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"412":{"content":{"application/json":{"example":{"data":{},"error":"Precondition Failed","message":"Could not find pocket b7e3f8a9-4c1d-4e2f-8a3c-5d6e7f8a9b0c associated to user ac859110-e934-42d8-8643-a7e2de42349c","statusCode":412},"schema":{"description":"Business error returned by the operation.","properties":{"data":{"additionalProperties":true,"description":"Additional detail about the error. An empty object when there is none.","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Precondition Failed","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Could not find pocket b7e3f8a9-4c1d-4e2f-8a3c-5d6e7f8a9b0c associated to user ac859110-e934-42d8-8643-a7e2de42349c","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":412,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"}}},"description":"The pocket does not exist or does not belong to the authenticated user."},"428":{"content":{"application/json":{"example":{"data":{},"error":"Precondition Required","message":"Low verification tier","statusCode":428},"schema":{"description":"Business error returned by the operation.","properties":{"data":{"additionalProperties":true,"description":"Additional detail about the error. An empty object when there is none.","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Precondition Failed","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Could not find pocket b7e3f8a9-4c1d-4e2f-8a3c-5d6e7f8a9b0c associated to user ac859110-e934-42d8-8643-a7e2de42349c","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":412,"type":"integer"}},"required":["statusCode","error","message","data"],"type":"object"}}},"description":"The user has not completed the identity verification required to deposit."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get pocket reference","tags":["Teller"],"x-product":{"wallet":"Funding"}}},"/v1/trading/candle":{"get":{"description":"Returns OHLCV candles (open, high, low, close, volume) of a market between `startTime` and\n`endTime`. No authentication is required. Sort by the timestamp (`[0]`) before plotting.\n\nThe last candle is the current one and is still changing. Intervals with no trades produce\nno candle, so the series can have gaps: fill them on the client if a continuous series is\nneeded.\n\nA request returns at most `limit` candles. To cover a longer range, split it into windows\nof `limit * interval` and request them one after another.\n","parameters":[{"description":"Market as `BASE/QUOTE`.","in":"query","name":"symbol","required":true,"schema":{"description":"Market symbol as `BASE/QUOTE`, uppercase and separated by a slash (`BTC/EUR`). The hyphenated\nform (`BTC-EUR`) is not accepted: order creation answers `400 Symbol BTC-EUR is wrong` and the\nmarket data endpoints answer `404 Market not found for symbol BTC-EUR`. The list of valid\nsymbols is `GET /v2/trading/market-config`.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"}},{"description":"Candle duration in minutes (`1`, `5`, `15`, `30`, `60`, `240`, `1440`), or `1D` for daily\ncandles.\n","in":"query","name":"interval","required":true,"schema":{"enum":["1","5","15","30","60","240","1440","1D"],"example":"60","type":"string"}},{"description":"Start of the range, in Unix epoch milliseconds. Defaults to 24 hours before the request.","in":"query","name":"startTime","schema":{"example":1712494800000,"format":"int64","type":"integer"}},{"description":"End of the range, in Unix epoch milliseconds. Defaults to now; a future value is treated as now.","in":"query","name":"endTime","schema":{"example":1712581200000,"format":"int64","type":"integer"}},{"description":"Maximum number of candles. Default and documented maximum `1000`.","in":"query","name":"limit","schema":{"default":1000,"example":100,"maximum":1000,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"example":[[1712494800000,69321.2,69492,69294.3,69346.9,1.58942378],[1712498400000,69344.3,69637.2,69225.8,69583.7,8.52748622]],"schema":{"items":{"description":"One candle as a positional tuple `[timestamp, open, high, low, close, volume]`: `timestamp`\nis the candle's opening time in Unix epoch milliseconds, the four prices are in the quote\ncurrency, and `volume` is in the base currency.\n","example":[1712494800000,69321.2,69492,69294.3,69346.9,1.58942378],"items":{"type":"number"},"maxItems":6,"minItems":6,"type":"array"},"type":"array"}}},"description":"Candles of the range."},"400":{"content":{"application/json":{"example":{"errors":[{"code":"INVALID_REQUEST_PARAMETER","errors":[{"code":"REQUIRED","message":"Value is required but was not provided"}],"in":"query","message":"Invalid parameter (interval): Value is required but was not provided","name":"interval"}],"message":"Validation errors"},"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"`symbol` or `interval` was not sent, or a parameter has the wrong type."},"404":{"content":{"application/json":{"example":{"error":"Not Found","message":"Market not found for symbol BTC-EUR","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":404},"schema":{"description":"Business error from the trading service. `message` is human-readable and may change; when\n`errorPayload.code` is present, branch on it instead.\n","properties":{"error":{"description":"Standard reason phrase of the status (`Bad Request`, `Not Found`, `Precondition Failed`...).","example":"Precondition Failed","type":"string"},"errorPayload":{"additionalProperties":true,"description":"Machine-readable detail. Present only on order creation, order cancellation, order trades\nand trading wallet deposits and withdrawals: `null` there when the error has no detail\n(deposits and withdrawals omit it instead). `code` identifies the error; the other\nproperties depend on it (for example `minAmount` for `ORDER_AMOUNT_LOWER_MARKET_MIN`).\n","nullable":true,"properties":{"code":{"description":"Stable error code.","example":"ORDER_AMOUNT_LOWER_MARKET_MIN","type":"string"}},"type":"object"},"message":{"description":"What went wrong, in English.","example":"The order amount can not be lower than 0.0001","type":"string"},"reqId":{"description":"Request identifier. Quote it when reporting an incident.","example":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","type":"string"},"statusCode":{"description":"Same value as the HTTP status.","example":412,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"No market with this symbol exists."},"429":{"content":{"application/json":{"example":{"error":"Too Many Requests"},"schema":{"description":"Too many requests in a short time. The `Retry-After` header holds the seconds to wait before\nretrying.\n","properties":{"error":{"description":"Always `Too Many Requests`.","example":"Too Many Requests","type":"string"}},"required":["error"],"type":"object"}}},"description":"Rate limit exceeded. Wait the seconds in the `Retry-After` header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}}}},"summary":"Get OHLCV candles","tags":["Trading"],"x-product":{"spot":"MarketData"}}},"/v1/trading/market-config":{"get":{"deprecated":true,"description":"Returns the markets available to the caller and the rules an order must respect in each\none: amount and price limits, minimum order value and decimal precision. Validate orders\nagainst these values before sending them to avoid `412` rejections.\n\nAuthentication is optional and changes the result: `restricted` markets are listed only for\nthe users granted access, `disabled` markets are never listed, and `enabled_at` markets are\nlisted once their opening date has passed.\n\nDeprecated: `feeMakerPercentage` and `feeTakerPercentage` are always `0` in this version.\n","parameters":[{"description":"Only this market, as `BASE/QUOTE`. The response is still an array, empty when the market does not exist.","in":"query","name":"symbol","schema":{"description":"Market symbol as `BASE/QUOTE`, uppercase and separated by a slash (`BTC/EUR`). The hyphenated\nform (`BTC-EUR`) is not accepted: order creation answers `400 Symbol BTC-EUR is wrong` and the\nmarket data endpoints answer `404 Market not found for symbol BTC-EUR`. The list of valid\nsymbols is `GET /v2/trading/market-config`.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"}},{"description":"Maximum number of markets to return. All of them when omitted.","in":"query","name":"limit","schema":{"example":50,"minimum":1,"type":"integer"}},{"description":"Number of markets to skip.","in":"query","name":"offset","schema":{"default":0,"example":0,"minimum":0,"type":"integer"}},{"description":"Field to sort by. Any other value is ignored.","in":"query","name":"sort","schema":{"default":"symbol","enum":["id","symbol","minAmount","maxAmount","minPrice","maxPrice","tickSize","minOrderSize","pricePrecision","amountPrecision"],"example":"symbol","type":"string"}},{"description":"Sort direction. Any other value is ignored.","in":"query","name":"direction","schema":{"enum":["asc","desc"],"example":"asc","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":[{"amountPrecision":6,"feeMakerPercentage":0,"feeTakerPercentage":0,"id":"767a9906-3757-4d9c-8d90-504eb0a35a18","initialPrice":0,"marketEnabled":"enabled","marketEnabledAt":null,"maxAmount":20,"maxPrice":1000000,"minAmount":0.0001,"minOrderSize":1,"minPrice":1000,"pricePrecision":4,"symbol":"BTC/EUR","tickSize":0.000001}],"schema":{"items":{"description":"Trading rules of one market. Orders that break them are rejected with `412`.","properties":{"amountPrecision":{"description":"Maximum decimal places accepted in `amount`.","example":6,"minimum":0,"type":"integer"},"feeMakerPercentage":{"description":"Always `0` in this version; it does not reflect the fee charged. The fee actually applied is on each trade (`feePercentage`).","example":0,"type":"number"},"feeTakerPercentage":{"description":"Always `0` in this version; it does not reflect the fee charged. The fee actually applied is on each trade (`feePercentage`).","example":0,"type":"number"},"id":{"description":"Market identifier.","example":"767a9906-3757-4d9c-8d90-504eb0a35a18","format":"uuid","type":"string"},"initialPrice":{"description":"Reference price of a market that has not opened yet: until `marketEnabledAt`, buy orders\nmust be priced at or below it and sell orders at or above it. `0` when not applicable.\n","example":0,"minimum":0,"type":"number"},"marketEnabled":{"description":"- `enabled`: open for trading.\n- `enabled_at`: opens at `marketEnabledAt`. It is listed only once that date has passed.\n- `frozen`: listed, but new orders and cancellations are rejected with `412`.\n- `restricted`: open only to the users granted access; it is listed only for them.\n- `disabled`: closed. It never appears in the listings.\n","enum":["enabled","enabled_at","frozen","restricted","disabled"],"example":"enabled","type":"string"},"marketEnabledAt":{"description":"Opening date of an `enabled_at` market; `null` for every other state.","example":"2024-06-03T10:00:00.000Z","format":"date-time","nullable":true,"type":"string"},"maxAmount":{"description":"Maximum order amount, in the base currency.","example":20,"minimum":0,"type":"number"},"maxPrice":{"description":"Maximum order price, in the quote currency.","example":1000000,"minimum":0,"type":"number"},"minAmount":{"description":"Minimum order amount, in the base currency.","example":0.0001,"minimum":0,"type":"number"},"minOrderSize":{"description":"Minimum order value (`amount * price`), in the quote currency.","example":1,"minimum":0,"type":"number"},"minPrice":{"description":"Minimum order price, in the quote currency.","example":1000,"minimum":0,"type":"number"},"pricePrecision":{"description":"Maximum decimal places accepted in `price` and `stopPrice`.","example":4,"minimum":0,"type":"integer"},"symbol":{"description":"Market symbol as `BASE/QUOTE`, uppercase and separated by a slash (`BTC/EUR`). The hyphenated\nform (`BTC-EUR`) is not accepted: order creation answers `400 Symbol BTC-EUR is wrong` and the\nmarket data endpoints answer `404 Market not found for symbol BTC-EUR`. The list of valid\nsymbols is `GET /v2/trading/market-config`.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"},"tickSize":{"deprecated":true,"description":"Smallest price increment as a decimal number. Deprecated; use `pricePrecision`.","example":0.000001,"minimum":0,"type":"number"}},"type":"object"},"type":"array"}}},"description":"Markets and their rules; an empty array when none matches."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]},{"NoAuth":[]}],"summary":"List market configurations","tags":["Trading"],"x-product":{"spot":"MarketData"},"x-use":"GET /v2/trading/market-config"}},"/v1/trading/movement":{"get":{"description":"Returns the movements of funds into and out of the authenticated user's trading wallet,\nnewest first: their own deposits and withdrawals, adjustments made by Bit2Me, automatic\nworking capital refills and funds assigned to or released from their trading bots.\n\nAt most 100 movements are returned and there is no offset: when more could match, split the\nquery into shorter `from`/`to` ranges.\n","parameters":[{"description":"Only movements of this trading wallet (the `id` from `GET /v1/trading/wallet/balance`).","in":"query","name":"walletId","schema":{"example":"3a9f1c2d-7e4b-4f6a-8c1d-2b3e4f5a6b7c","format":"uuid","type":"string"}},{"description":"Only movements of this currency.","in":"query","name":"currency","schema":{"example":"BTC","pattern":"^[A-Z0-9]+$","type":"string"}},{"description":"Only movements created at or after this date (ISO 8601).","in":"query","name":"from","schema":{"example":"2025-01-01T00:00:00Z","format":"date-time","type":"string"}},{"description":"Only movements created at or before this date (ISO 8601).","in":"query","name":"to","schema":{"example":"2025-12-31T23:59:59Z","format":"date-time","type":"string"}},{"description":"Only movements issued by this origin (see `serviceOrderName` in the response).","in":"query","name":"serviceOrderName","schema":{"enum":["wallet","admin","working-capital","bot"],"example":"wallet","type":"string"}},{"description":"Only deposits or only withdrawals.","in":"query","name":"movementType","schema":{"enum":["deposit","withdrawal"],"example":"deposit","type":"string"}},{"description":"Maximum number of movements. Default and maximum `100`; a larger value is rejected with `400`.","in":"query","name":"limit","schema":{"default":100,"example":50,"maximum":100,"minimum":1,"type":"number"}}],"responses":{"200":{"content":{"application/json":{"example":[{"amount":100,"createdAt":"2025-03-10T09:30:00.000Z","currency":"EUR","id":"1b2c3d4e-5f60-4718-9a2b-3c4d5e6f7a8b","movementType":"deposit","serviceOrderName":"wallet","status":"completed","walletId":"3a9f1c2d-7e4b-4f6a-8c1d-2b3e4f5a6b7c"},{"amount":50,"createdAt":"2025-03-11T17:02:41.000Z","currency":"EUR","id":"8a7b6c5d-4e3f-4210-9fed-cba987654321","movementType":"withdrawal","serviceOrderName":"wallet","status":"completed","walletId":"3a9f1c2d-7e4b-4f6a-8c1d-2b3e4f5a6b7c"}],"schema":{"items":{"description":"A transfer of funds into or out of the user's trading wallet.","properties":{"amount":{"description":"Amount moved, in `currency`.","example":100,"minimum":0,"type":"number"},"createdAt":{"description":"When the movement was requested. The list is sorted by it, newest first.","example":"2025-03-10T09:30:00.000Z","format":"date-time","type":"string"},"currency":{"description":"Currency code of the movement.","example":"EUR","pattern":"^[A-Z0-9]+$","type":"string"},"id":{"description":"Movement identifier.","example":"1b2c3d4e-5f60-4718-9a2b-3c4d5e6f7a8b","format":"uuid","type":"string"},"movementType":{"description":"`deposit` moves funds into the trading wallet, `withdrawal` moves them out.","enum":["deposit","withdrawal"],"example":"deposit","type":"string"},"serviceOrderName":{"description":"Who issued the movement: `wallet` for the user's own deposits and withdrawals, `admin`\nfor adjustments made by Bit2Me, `working-capital` for automatic working capital refills\nand `bot` for funds assigned to or released from the user's trading bots.\n","enum":["wallet","admin","working-capital","bot"],"example":"wallet","type":"string"},"status":{"description":"- `pending`: in progress. While a movement is `pending`, new deposits and withdrawals of\n  the same currency are rejected with `412`.\n- `completed`: the funds were moved.\n- `error`: the movement could not be completed.\n","enum":["pending","completed","error"],"example":"completed","type":"string"},"walletId":{"description":"Trading wallet affected (the `id` from `GET /v1/trading/wallet/balance`).","example":"3a9f1c2d-7e4b-4f6a-8c1d-2b3e4f5a6b7c","format":"uuid","type":"string"}},"required":["id","movementType","amount","createdAt","walletId","currency","status","serviceOrderName"],"type":"object"},"type":"array"}}},"description":"Movements matching the filters; an empty array when none match."},"400":{"content":{"application/json":{"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"A parameter has the wrong type or is out of range, for example `limit` above 100."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The API key, signature or nonce could not be validated."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"List historical movements","tags":["Trading"],"x-product":{"spot":"Funding"}}},"/v1/trading/order":{"get":{"description":"Returns the authenticated user's spot orders, filtered and paginated.\n\nAt most 100 orders are returned per call: a larger `limit` is silently reduced to 100, so\npage with `offset` until a page comes back shorter than `limit`.\n\nOpen orders include `inactive` ones (stop-limit orders waiting for their trigger). To list\neverything still pending, filter with `status_in=open,inactive` rather than `status=open`.\n","parameters":[{"description":"Comma-separated order identifiers, up to 20. Any value that is not a UUID is rejected with `400`.","in":"query","name":"ids","schema":{"example":"536ee1dc-528a-419e-9c00-5e04c010658d,0f5c3e7a-2b1d-4c8e-9f6a-7d2e1b3c4a5f","type":"string"}},{"description":"Comma-separated client order identifiers (the values sent as `clientOrderId` on creation), each up to 48 characters.","in":"query","name":"clientOrderId","schema":{"example":"my-bot-order-0001","type":"string"}},{"description":"Only orders of this market, as `BASE/QUOTE`.","in":"query","name":"symbol","schema":{"description":"Market symbol as `BASE/QUOTE`, uppercase and separated by a slash (`BTC/EUR`). The hyphenated\nform (`BTC-EUR`) is not accepted: order creation answers `400 Symbol BTC-EUR is wrong` and the\nmarket data endpoints answer `404 Market not found for symbol BTC-EUR`. The list of valid\nsymbols is `GET /v2/trading/market-config`.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"}},{"description":"Only orders of this side.","in":"query","name":"side","schema":{"description":"`buy` spends the quote currency to get the base currency; `sell` does the opposite.","enum":["buy","sell"],"example":"buy","type":"string"}},{"description":"Only orders of this type.","in":"query","name":"orderType","schema":{"description":"- `limit`: rests in the book at `price` or better.\n- `market`: executes immediately against the book at the best available prices.\n- `stop-limit`: stays `inactive` until the market reaches `stopPrice`, then becomes a limit order at `price`.\n","enum":["limit","stop-limit","market"],"example":"limit","type":"string"}},{"description":"Only orders in exactly this status.","in":"query","name":"status","schema":{"description":"- `open`: in the order book, waiting to be filled; may be partially filled.\n- `inactive`: a `stop-limit` order whose `stopPrice` has not been reached yet. It is not in the\n  order book, but it holds funds and can be cancelled.\n- `filled`: completely executed.\n- `cancelled`: cancelled by the user, by Bit2Me or by its time-in-force; see `cancelReason`.\n  It may have been partially filled before.\n","enum":["open","inactive","filled","cancelled"],"example":"open","type":"string"}},{"description":"Only orders not in this status.","in":"query","name":"status_ne","schema":{"description":"- `open`: in the order book, waiting to be filled; may be partially filled.\n- `inactive`: a `stop-limit` order whose `stopPrice` has not been reached yet. It is not in the\n  order book, but it holds funds and can be cancelled.\n- `filled`: completely executed.\n- `cancelled`: cancelled by the user, by Bit2Me or by its time-in-force; see `cancelReason`.\n  It may have been partially filled before.\n","enum":["open","inactive","filled","cancelled"],"example":"open","type":"string"}},{"description":"Comma-separated statuses to include (`open`, `inactive`, `filled`, `cancelled`).","in":"query","name":"status_in","schema":{"example":"open,inactive","type":"string"}},{"description":"Comma-separated statuses to exclude (`open`, `inactive`, `filled`, `cancelled`).","in":"query","name":"status_ni","schema":{"example":"cancelled","type":"string"}},{"description":"Only orders created at or after this date (ISO 8601). `startTime` and `endTime` must be sent\ntogether, and `startTime` must not be later than `endTime`; otherwise `400`.\n","in":"query","name":"startTime","schema":{"example":"2024-05-01T00:00:00.000Z","format":"date-time","type":"string"}},{"description":"Only orders created at or before this date (ISO 8601). Sent together with `startTime`.","in":"query","name":"endTime","schema":{"example":"2024-05-31T23:59:59.999Z","format":"date-time","type":"string"}},{"description":"Page size. Default and maximum `100`; larger values are reduced to `100`.","in":"query","name":"limit","schema":{"default":100,"example":20,"maximum":100,"minimum":1,"type":"number"}},{"description":"Number of orders to skip.","in":"query","name":"offset","schema":{"default":0,"example":0,"minimum":0,"type":"number"}},{"description":"Order field to sort by, for example `createdAt`.","in":"query","name":"sort","schema":{"example":"createdAt","type":"string"}},{"description":"Sort direction.","in":"query","name":"direction","schema":{"enum":["asc","desc"],"example":"desc","type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"openAndFilled":{"summary":"An open limit order and a filled one","value":[{"cancelReason":null,"clientOrderId":null,"cost":0,"createdAt":"2024-05-07T14:08:30.961Z","feeAmount":0,"feeCurrency":"EUR","filledAmount":0,"id":"536ee1dc-528a-419e-9c00-5e04c010658d","orderAmount":0.35,"orderType":"limit","postOnly":null,"price":65000.5,"side":"buy","status":"open","stopPrice":0,"symbol":"BTC/EUR","timeInForce":"GTC","updatedAt":"2024-05-07T14:08:30.961Z","userId":"2bf436fc-43e6-459a-b647-6b446f72ad96"},{"cancelReason":null,"clientOrderId":"my-bot-order-0001","cost":649.87,"createdAt":"2024-05-06T09:12:03.114Z","feeAmount":1.94961,"feeCurrency":"EUR","filledAmount":0.01,"id":"0f5c3e7a-2b1d-4c8e-9f6a-7d2e1b3c4a5f","orderAmount":0.01,"orderType":"market","postOnly":null,"price":0,"side":"sell","status":"filled","stopPrice":0,"symbol":"BTC/EUR","timeInForce":"GTC","updatedAt":"2024-05-06T09:12:03.402Z","userId":"2bf436fc-43e6-459a-b647-6b446f72ad96"}]},"withoutMatches":{"summary":"No order matches the filters","value":[]}},"schema":{"items":{"description":"A spot order of the authenticated user.","properties":{"cancelReason":{"description":"Why the order was cancelled, `null` otherwise. It starts with a stable code:\n`CR-1` user request, `CR-2` admin request, `CR-3` order expired, `CR-4` matching engine,\n`CR-5` and `CR-6` internal error, `CR-7` self trade, `CR-8` time in force.\nBranch on the code, not on the text after it.\n","example":"CR-1: User request","nullable":true,"pattern":"^CR-[0-9]+","type":"string"},"clientOrderId":{"description":"Identifier supplied by the client when creating the order, or `null`.","example":"my-bot-order-0001","maxLength":48,"nullable":true,"type":"string"},"cost":{"description":"Value executed so far, in the quote currency. `0` until something fills.","example":0,"minimum":0,"type":"number"},"createdAt":{"description":"When the order was created.","example":"2024-05-07T14:08:30.961Z","format":"date-time","type":"string"},"feeAmount":{"description":"Fees accumulated by the order's trades, in `feeCurrency`.","example":0,"minimum":0,"type":"number"},"feeCurrency":{"description":"Currency of `feeAmount`.","example":"EUR","pattern":"^[A-Z0-9]+$","type":"string"},"filledAmount":{"description":"Part of `orderAmount` already executed, in the base currency.","example":0,"minimum":0,"type":"number"},"id":{"description":"Order identifier.","example":"536ee1dc-528a-419e-9c00-5e04c010658d","format":"uuid","type":"string"},"orderAmount":{"description":"Order size in the base currency. For a market order sent with `amountInQuote`, the base amount computed from the order book.","example":0.35,"minimum":0,"type":"number"},"orderType":{"description":"- `limit`: rests in the book at `price` or better.\n- `market`: executes immediately against the book at the best available prices.\n- `stop-limit`: stays `inactive` until the market reaches `stopPrice`, then becomes a limit order at `price`.\n","enum":["limit","stop-limit","market"],"example":"limit","type":"string"},"postOnly":{"description":"The `postOnly` flag sent on creation, or `null` when it was not sent.","example":false,"nullable":true,"type":"boolean"},"price":{"description":"Limit price in the quote currency. `0` for `market` orders.","example":65000.5,"minimum":0,"type":"number"},"side":{"description":"`buy` spends the quote currency to get the base currency; `sell` does the opposite.","enum":["buy","sell"],"example":"buy","type":"string"},"status":{"description":"- `open`: in the order book, waiting to be filled; may be partially filled.\n- `inactive`: a `stop-limit` order whose `stopPrice` has not been reached yet. It is not in the\n  order book, but it holds funds and can be cancelled.\n- `filled`: completely executed.\n- `cancelled`: cancelled by the user, by Bit2Me or by its time-in-force; see `cancelReason`.\n  It may have been partially filled before.\n","enum":["open","inactive","filled","cancelled"],"example":"open","type":"string"},"stopPrice":{"description":"Trigger price of a `stop-limit` order, in the quote currency. `0` for other order types.","example":0,"minimum":0,"type":"number"},"symbol":{"description":"Market symbol as `BASE/QUOTE`, uppercase and separated by a slash (`BTC/EUR`). The hyphenated\nform (`BTC-EUR`) is not accepted: order creation answers `400 Symbol BTC-EUR is wrong` and the\nmarket data endpoints answer `404 Market not found for symbol BTC-EUR`. The list of valid\nsymbols is `GET /v2/trading/market-config`.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"},"timeInForce":{"default":"GTC","description":"How long the order may stay in the order book before being cancelled.\n- `GTC` (good 'til cancelled), the default: rests in the book until filled or cancelled.\n- `FOK` (fill or kill): executes completely and immediately, or is cancelled without any fill.\n  Only for `limit` orders.\n- `IOC` (immediate or cancel): part of the contract but not available on Bit2Me markets; the\n  order is rejected with `412` and `errorPayload.code` `TIME_IN_FORCE_NOT_AVAILABLE`.\n\n`market` and `stop-limit` orders accept only `GTC` (`412` `TIME_IN_FORCE_INVALID` otherwise).\n","enum":["GTC","IOC","FOK"],"example":"GTC","type":"string"},"updatedAt":{"description":"Last time the order changed (a fill, a cancellation, a stop trigger).","example":"2024-05-07T14:08:30.961Z","format":"date-time","type":"string"},"userId":{"description":"Owner of the order.","example":"2bf436fc-43e6-459a-b647-6b446f72ad96","format":"uuid","type":"string"}},"type":"object"},"type":"array"}}},"description":"The page of orders; an empty array when none match."},"400":{"content":{"application/json":{"examples":{"incompleteRange":{"summary":"Only one of `startTime` and `endTime` was sent","value":{"error":"Bad Request","message":"startTime and endTime are mandatory when one of them is specified","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":400}},"invalidId":{"summary":"An entry of `ids` is not a UUID","value":{"error":"Bad Request","message":"Invalid order id: 123","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":400}},"tooManyIds":{"summary":"More than 20 identifiers in `ids`","value":{"error":"Bad Request","message":"Max 20 order identifiers are allowed","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":400}}},"schema":{"oneOf":[{"description":"Business error from the trading service. `message` is human-readable and may change; when\n`errorPayload.code` is present, branch on it instead.\n","properties":{"error":{"description":"Standard reason phrase of the status (`Bad Request`, `Not Found`, `Precondition Failed`...).","example":"Precondition Failed","type":"string"},"errorPayload":{"additionalProperties":true,"description":"Machine-readable detail. Present only on order creation, order cancellation, order trades\nand trading wallet deposits and withdrawals: `null` there when the error has no detail\n(deposits and withdrawals omit it instead). `code` identifies the error; the other\nproperties depend on it (for example `minAmount` for `ORDER_AMOUNT_LOWER_MARKET_MIN`).\n","nullable":true,"properties":{"code":{"description":"Stable error code.","example":"ORDER_AMOUNT_LOWER_MARKET_MIN","type":"string"}},"type":"object"},"message":{"description":"What went wrong, in English.","example":"The order amount can not be lower than 0.0001","type":"string"},"reqId":{"description":"Request identifier. Quote it when reporting an incident.","example":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","type":"string"},"statusCode":{"description":"Same value as the HTTP status.","example":412,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"},{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}]}}},"description":"A filter is malformed. The body is a `TradingErrorResponse` for the checks made by the\ntrading service (`ids`, dates), or a `RequestValidationErrorResponse` when a parameter does\nnot match its declared type.\n"},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The API key, signature or nonce could not be validated."},"429":{"content":{"application/json":{"example":{"error":"Too Many Requests"},"schema":{"description":"Too many requests in a short time. The `Retry-After` header holds the seconds to wait before\nretrying.\n","properties":{"error":{"description":"Always `Too Many Requests`.","example":"Too Many Requests","type":"string"}},"required":["error"],"type":"object"}}},"description":"Rate limit exceeded. Wait the seconds in the `Retry-After` header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}}}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"List trading orders","tags":["Trading"],"x-product":{"spot":"Trading"}},"post":{"description":"Creates a spot order for the authenticated user and returns it as stored.\n\n- `limit`: `price` is required.\n- `stop-limit`: `price` and `stopPrice` are required. The order is created `inactive` and\n  enters the book as a limit order at `price` once the market reaches `stopPrice`.\n- `market`: `price` is ignored. With `amountInQuote: true`, `amount` is read in the quote\n  currency and converted to the base amount from the current order book.\n\nAmounts and prices are decimal strings. They must respect the market rules published by\n`GET /v1/trading/market-config` (`minAmount`, `maxAmount`, `minPrice`, `maxPrice`,\n`minOrderSize`, `pricePrecision`, `amountPrecision`); an order that breaks one is rejected with\n`412` and an `errorPayload.code` that names the rule.\n\nFollow the order's progress with `GET /v1/trading/order/{id}` and its fills with\n`GET /v1/trading/order/{id}/trades`.\n","requestBody":{"content":{"application/json":{"examples":{"limit":{"summary":"Limit buy","value":{"amount":"0.35","orderType":"limit","price":"65000.5","side":"buy","symbol":"BTC/EUR"}},"market":{"summary":"Market sell","value":{"amount":"0.01","orderType":"market","side":"sell","symbol":"BTC/EUR"}},"marketInQuote":{"summary":"Market buy for 100 EUR","value":{"amount":"100","amountInQuote":true,"orderType":"market","side":"buy","symbol":"BTC/EUR"}},"stopLimit":{"summary":"Stop-limit sell with a client identifier","value":{"amount":"0.1","clientOrderId":"my-bot-order-0002","orderType":"stop-limit","price":"63900","side":"sell","stopPrice":"64000","symbol":"BTC/EUR"}}},"schema":{"properties":{"amount":{"allOf":[{"maxLength":50,"minLength":1,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}],"description":"Order size in the base currency, or in the quote currency when `amountInQuote` is `true`.","example":"0.35"},"amountInQuote":{"default":false,"description":"Read `amount` in the quote currency. Only for `market` orders (`412`\n`AMOUNT_IN_QUOTE_INVALID_ORDER_TYPE` otherwise), and rejected with `412`\n`NOT_ENOUGH_LIQUIDITY` when the book cannot absorb it.\n","example":false,"type":"boolean"},"clientOrderId":{"description":"Your own identifier for the order, returned on the order and its trades and usable as a filter. Up to 48 characters.","example":"my-bot-order-0001","maxLength":48,"type":"string"},"orderType":{"description":"- `limit`: rests in the book at `price` or better.\n- `market`: executes immediately against the book at the best available prices.\n- `stop-limit`: stays `inactive` until the market reaches `stopPrice`, then becomes a limit order at `price`.\n","enum":["limit","stop-limit","market"],"example":"limit","type":"string"},"postOnly":{"description":"Stored with the order and returned in `postOnly`.","example":false,"type":"boolean"},"price":{"allOf":[{"maxLength":50,"minLength":1,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}],"description":"Limit price in the quote currency. Required for `limit` and `stop-limit`; ignored for `market`.","example":"65000.5"},"side":{"description":"`buy` spends the quote currency to get the base currency; `sell` does the opposite.","enum":["buy","sell"],"example":"buy","type":"string"},"stopPrice":{"allOf":[{"maxLength":50,"minLength":1,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}],"description":"Trigger price in the quote currency. Required for `stop-limit`; ignored otherwise.","example":"64000"},"symbol":{"allOf":[{"description":"Market symbol as `BASE/QUOTE`, uppercase and separated by a slash (`BTC/EUR`). The hyphenated\nform (`BTC-EUR`) is not accepted: order creation answers `400 Symbol BTC-EUR is wrong` and the\nmarket data endpoints answer `404 Market not found for symbol BTC-EUR`. The list of valid\nsymbols is `GET /v2/trading/market-config`.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"}],"description":"Market as `BASE/QUOTE`. Any other format is rejected with `400`."},"timeInForce":{"default":"GTC","description":"How long the order may stay in the order book before being cancelled.\n- `GTC` (good 'til cancelled), the default: rests in the book until filled or cancelled.\n- `FOK` (fill or kill): executes completely and immediately, or is cancelled without any fill.\n  Only for `limit` orders.\n- `IOC` (immediate or cancel): part of the contract but not available on Bit2Me markets; the\n  order is rejected with `412` and `errorPayload.code` `TIME_IN_FORCE_NOT_AVAILABLE`.\n\n`market` and `stop-limit` orders accept only `GTC` (`412` `TIME_IN_FORCE_INVALID` otherwise).\n","enum":["GTC","IOC","FOK"],"example":"GTC","type":"string"}},"required":["side","symbol","amount","orderType"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"examples":{"limit":{"summary":"Limit buy resting in the book","value":{"cancelReason":null,"clientOrderId":null,"cost":0,"createdAt":"2024-05-07T14:08:30.961Z","feeAmount":0,"feeCurrency":"EUR","filledAmount":0,"id":"536ee1dc-528a-419e-9c00-5e04c010658d","orderAmount":0.35,"orderType":"limit","postOnly":null,"price":65000.5,"side":"buy","status":"open","stopPrice":0,"symbol":"BTC/EUR","timeInForce":"GTC","updatedAt":"2024-05-07T14:08:30.961Z","userId":"2bf436fc-43e6-459a-b647-6b446f72ad96"}},"stopLimit":{"summary":"Stop-limit waiting for its trigger","value":{"cancelReason":null,"clientOrderId":"my-bot-order-0002","cost":0,"createdAt":"2024-05-07T14:10:11.020Z","feeAmount":0,"feeCurrency":"EUR","filledAmount":0,"id":"7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f","orderAmount":0.1,"orderType":"stop-limit","postOnly":null,"price":63900,"side":"sell","status":"inactive","stopPrice":64000,"symbol":"BTC/EUR","timeInForce":"GTC","updatedAt":"2024-05-07T14:10:11.020Z","userId":"2bf436fc-43e6-459a-b647-6b446f72ad96"}}},"schema":{"description":"A spot order of the authenticated user.","properties":{"cancelReason":{"description":"Why the order was cancelled, `null` otherwise. It starts with a stable code:\n`CR-1` user request, `CR-2` admin request, `CR-3` order expired, `CR-4` matching engine,\n`CR-5` and `CR-6` internal error, `CR-7` self trade, `CR-8` time in force.\nBranch on the code, not on the text after it.\n","example":"CR-1: User request","nullable":true,"pattern":"^CR-[0-9]+","type":"string"},"clientOrderId":{"description":"Identifier supplied by the client when creating the order, or `null`.","example":"my-bot-order-0001","maxLength":48,"nullable":true,"type":"string"},"cost":{"description":"Value executed so far, in the quote currency. `0` until something fills.","example":0,"minimum":0,"type":"number"},"createdAt":{"description":"When the order was created.","example":"2024-05-07T14:08:30.961Z","format":"date-time","type":"string"},"feeAmount":{"description":"Fees accumulated by the order's trades, in `feeCurrency`.","example":0,"minimum":0,"type":"number"},"feeCurrency":{"description":"Currency of `feeAmount`.","example":"EUR","pattern":"^[A-Z0-9]+$","type":"string"},"filledAmount":{"description":"Part of `orderAmount` already executed, in the base currency.","example":0,"minimum":0,"type":"number"},"id":{"description":"Order identifier.","example":"536ee1dc-528a-419e-9c00-5e04c010658d","format":"uuid","type":"string"},"orderAmount":{"description":"Order size in the base currency. For a market order sent with `amountInQuote`, the base amount computed from the order book.","example":0.35,"minimum":0,"type":"number"},"orderType":{"description":"- `limit`: rests in the book at `price` or better.\n- `market`: executes immediately against the book at the best available prices.\n- `stop-limit`: stays `inactive` until the market reaches `stopPrice`, then becomes a limit order at `price`.\n","enum":["limit","stop-limit","market"],"example":"limit","type":"string"},"postOnly":{"description":"The `postOnly` flag sent on creation, or `null` when it was not sent.","example":false,"nullable":true,"type":"boolean"},"price":{"description":"Limit price in the quote currency. `0` for `market` orders.","example":65000.5,"minimum":0,"type":"number"},"side":{"description":"`buy` spends the quote currency to get the base currency; `sell` does the opposite.","enum":["buy","sell"],"example":"buy","type":"string"},"status":{"description":"- `open`: in the order book, waiting to be filled; may be partially filled.\n- `inactive`: a `stop-limit` order whose `stopPrice` has not been reached yet. It is not in the\n  order book, but it holds funds and can be cancelled.\n- `filled`: completely executed.\n- `cancelled`: cancelled by the user, by Bit2Me or by its time-in-force; see `cancelReason`.\n  It may have been partially filled before.\n","enum":["open","inactive","filled","cancelled"],"example":"open","type":"string"},"stopPrice":{"description":"Trigger price of a `stop-limit` order, in the quote currency. `0` for other order types.","example":0,"minimum":0,"type":"number"},"symbol":{"description":"Market symbol as `BASE/QUOTE`, uppercase and separated by a slash (`BTC/EUR`). The hyphenated\nform (`BTC-EUR`) is not accepted: order creation answers `400 Symbol BTC-EUR is wrong` and the\nmarket data endpoints answer `404 Market not found for symbol BTC-EUR`. The list of valid\nsymbols is `GET /v2/trading/market-config`.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"},"timeInForce":{"default":"GTC","description":"How long the order may stay in the order book before being cancelled.\n- `GTC` (good 'til cancelled), the default: rests in the book until filled or cancelled.\n- `FOK` (fill or kill): executes completely and immediately, or is cancelled without any fill.\n  Only for `limit` orders.\n- `IOC` (immediate or cancel): part of the contract but not available on Bit2Me markets; the\n  order is rejected with `412` and `errorPayload.code` `TIME_IN_FORCE_NOT_AVAILABLE`.\n\n`market` and `stop-limit` orders accept only `GTC` (`412` `TIME_IN_FORCE_INVALID` otherwise).\n","enum":["GTC","IOC","FOK"],"example":"GTC","type":"string"},"updatedAt":{"description":"Last time the order changed (a fill, a cancellation, a stop trigger).","example":"2024-05-07T14:08:30.961Z","format":"date-time","type":"string"},"userId":{"description":"Owner of the order.","example":"2bf436fc-43e6-459a-b647-6b446f72ad96","format":"uuid","type":"string"}},"type":"object"}}},"description":"The order as created."},"400":{"content":{"application/json":{"examples":{"missingField":{"summary":"`amount` not sent","value":{"errors":[{"code":"INVALID_REQUEST_PARAMETER","errors":[{"code":"OBJECT_MISSING_REQUIRED_PROPERTY","message":"Missing required property: amount"}],"in":"body","message":"Invalid parameter (data): Value failed JSON Schema validation","name":"data"}],"message":"Validation errors"}},"wrongSymbol":{"summary":"Symbol with a hyphen instead of a slash","value":{"error":"Bad Request","errorPayload":null,"message":"Symbol BTC-EUR is wrong","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":400}}},"schema":{"oneOf":[{"description":"Business error from the trading service. `message` is human-readable and may change; when\n`errorPayload.code` is present, branch on it instead.\n","properties":{"error":{"description":"Standard reason phrase of the status (`Bad Request`, `Not Found`, `Precondition Failed`...).","example":"Precondition Failed","type":"string"},"errorPayload":{"additionalProperties":true,"description":"Machine-readable detail. Present only on order creation, order cancellation, order trades\nand trading wallet deposits and withdrawals: `null` there when the error has no detail\n(deposits and withdrawals omit it instead). `code` identifies the error; the other\nproperties depend on it (for example `minAmount` for `ORDER_AMOUNT_LOWER_MARKET_MIN`).\n","nullable":true,"properties":{"code":{"description":"Stable error code.","example":"ORDER_AMOUNT_LOWER_MARKET_MIN","type":"string"}},"type":"object"},"message":{"description":"What went wrong, in English.","example":"The order amount can not be lower than 0.0001","type":"string"},"reqId":{"description":"Request identifier. Quote it when reporting an incident.","example":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","type":"string"},"statusCode":{"description":"Same value as the HTTP status.","example":412,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"},{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}]}}},"description":"The request is malformed: a required field is missing or has the wrong type\n(`RequestValidationErrorResponse`), or `symbol` is not in `BASE/QUOTE` form\n(`TradingErrorResponse`).\n"},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The API key, signature or nonce could not be validated."},"404":{"content":{"application/json":{"example":{"error":"Not Found","errorPayload":null,"message":"Market not found for symbol ABC/EUR","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":404},"schema":{"description":"Business error from the trading service. `message` is human-readable and may change; when\n`errorPayload.code` is present, branch on it instead.\n","properties":{"error":{"description":"Standard reason phrase of the status (`Bad Request`, `Not Found`, `Precondition Failed`...).","example":"Precondition Failed","type":"string"},"errorPayload":{"additionalProperties":true,"description":"Machine-readable detail. Present only on order creation, order cancellation, order trades\nand trading wallet deposits and withdrawals: `null` there when the error has no detail\n(deposits and withdrawals omit it instead). `code` identifies the error; the other\nproperties depend on it (for example `minAmount` for `ORDER_AMOUNT_LOWER_MARKET_MIN`).\n","nullable":true,"properties":{"code":{"description":"Stable error code.","example":"ORDER_AMOUNT_LOWER_MARKET_MIN","type":"string"}},"type":"object"},"message":{"description":"What went wrong, in English.","example":"The order amount can not be lower than 0.0001","type":"string"},"reqId":{"description":"Request identifier. Quote it when reporting an incident.","example":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","type":"string"},"statusCode":{"description":"Same value as the HTTP status.","example":412,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"`symbol` is well formed but no such market exists."},"412":{"content":{"application/json":{"examples":{"amountBelowMin":{"summary":"Amount below the market minimum","value":{"error":"Precondition Failed","errorPayload":{"code":"ORDER_AMOUNT_LOWER_MARKET_MIN","minAmount":0.0001},"message":"The order amount can not be lower than 0.0001","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":412}},"notEnoughBalance":{"summary":"Not enough funds in the trading wallet","value":{"error":"Precondition Failed","errorPayload":{"code":"NOT_ENOUGH_BALANCE","currency":"BTC","orderAmount":0.5,"walletAmount":0.35},"message":"Not enough balance in the wallet. You want to sell 0.5 BTC but you have 0.35 BTC","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":412}},"pricePrecision":{"summary":"Too many decimals in the price","value":{"error":"Precondition Failed","errorPayload":{"code":"PRICE_PRECISION_EXCEEDED","pricePrecision":4},"message":"The max number of decimal places allowed for the price value is 4","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":412}}},"schema":{"description":"Business error from the trading service. `message` is human-readable and may change; when\n`errorPayload.code` is present, branch on it instead.\n","properties":{"error":{"description":"Standard reason phrase of the status (`Bad Request`, `Not Found`, `Precondition Failed`...).","example":"Precondition Failed","type":"string"},"errorPayload":{"additionalProperties":true,"description":"Machine-readable detail. Present only on order creation, order cancellation, order trades\nand trading wallet deposits and withdrawals: `null` there when the error has no detail\n(deposits and withdrawals omit it instead). `code` identifies the error; the other\nproperties depend on it (for example `minAmount` for `ORDER_AMOUNT_LOWER_MARKET_MIN`).\n","nullable":true,"properties":{"code":{"description":"Stable error code.","example":"ORDER_AMOUNT_LOWER_MARKET_MIN","type":"string"}},"type":"object"},"message":{"description":"What went wrong, in English.","example":"The order amount can not be lower than 0.0001","type":"string"},"reqId":{"description":"Request identifier. Quote it when reporting an incident.","example":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","type":"string"},"statusCode":{"description":"Same value as the HTTP status.","example":412,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The order was understood but cannot be placed. `errorPayload.code` says why; the most\ncommon codes are:\n\n- Market rules: `ORDER_AMOUNT_LOWER_MARKET_MIN`, `ORDER_AMOUNT_GREATER_MARKET_MAX`,\n  `AMOUNT_PRECISION_EXCEEDED`, `PRICE_LOWER_MARKET_MIN`, `PRICE_GREATER_MARKET_MAX`,\n  `PRICE_PRECISION_EXCEEDED`, `ORDER_SIZE_LOWER_MARKET_MIN`.\n- Prices: `ORDER_AMOUNT_LOWER_EQUAL_ZERO`, `ORDER_PRICE_LOWER_EQUAL_ZERO`,\n  `ORDER_STOP_PRICE_LOWER_EQUAL_ZERO`, `ORDER_STOP_PRICE_LOWER_LIMIT_PRICE`,\n  `ORDER_STOP_PRICE_GREATER_LIMIT_PRICE`.\n- Funds: `NOT_ENOUGH_BALANCE`, `TRADING_WALLET_NOT_FOUND`, `NOT_ENOUGH_LIQUIDITY`.\n- Options: `AMOUNT_IN_QUOTE_INVALID_ORDER_TYPE`, `TIME_IN_FORCE_INVALID`,\n  `TIME_IN_FORCE_NOT_AVAILABLE`.\n- Limits and availability: `MAX_OPEN_ORDERS_REACHED`, `MAX_CREATED_ORDERS_REACHED`,\n  `MARKET_CONFIG_NOT_FOUND`, `CREATE_ORDERS_DISABLED`, `CREATE_ORDERS_DISABLED_TEMPORALLY`,\n  `USER_IS_ALREADY_CREATING_ORDER` (another order of the same user is being created; retry).\n\nSome rejections carry no `errorPayload`, for example an invalid `side` or a market the\nuser has no access to (`Invalid market BTC/EUR`).\n"},"417":{"content":{"application/json":{"schema":{"description":"Business error from the trading service. `message` is human-readable and may change; when\n`errorPayload.code` is present, branch on it instead.\n","properties":{"error":{"description":"Standard reason phrase of the status (`Bad Request`, `Not Found`, `Precondition Failed`...).","example":"Precondition Failed","type":"string"},"errorPayload":{"additionalProperties":true,"description":"Machine-readable detail. Present only on order creation, order cancellation, order trades\nand trading wallet deposits and withdrawals: `null` there when the error has no detail\n(deposits and withdrawals omit it instead). `code` identifies the error; the other\nproperties depend on it (for example `minAmount` for `ORDER_AMOUNT_LOWER_MARKET_MIN`).\n","nullable":true,"properties":{"code":{"description":"Stable error code.","example":"ORDER_AMOUNT_LOWER_MARKET_MIN","type":"string"}},"type":"object"},"message":{"description":"What went wrong, in English.","example":"The order amount can not be lower than 0.0001","type":"string"},"reqId":{"description":"Request identifier. Quote it when reporting an incident.","example":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","type":"string"},"statusCode":{"description":"Same value as the HTTP status.","example":412,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The order passed validation but the matching engine could not register it. Retry later."},"429":{"content":{"application/json":{"example":{"error":"Too Many Requests"},"schema":{"description":"Too many requests in a short time. The `Retry-After` header holds the seconds to wait before\nretrying.\n","properties":{"error":{"description":"Always `Too Many Requests`.","example":"Too Many Requests","type":"string"}},"required":["error"],"type":"object"}}},"description":"Rate limit exceeded. Wait the seconds in the `Retry-After` header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}}}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Place a trading order","tags":["Trading"],"x-product":{"spot":"Trading"}}},"/v1/trading/order/{id}":{"delete":{"description":"Cancels one of the authenticated user's orders and returns it with `status: cancelled` and\n`cancelReason` starting with `CR-1`. The part already filled stays filled; the funds still\nreserved are released to the trading wallet.\n\nOnly `open` and `inactive` orders can be cancelled; any other status answers `412`\n`DELETE_CLOSED_ORDER`.\n","parameters":[{"description":"Order identifier (UUID). A value that is not a UUID is rejected with `400`.","example":"536ee1dc-528a-419e-9c00-5e04c010658d","in":"path","name":"id","required":true,"schema":{"example":"70b89183-c7fa-4460-91ce-34d53d739868","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"cancelled":{"summary":"Limit order cancelled by the user","value":{"cancelReason":"CR-1: User request","clientOrderId":null,"cost":0,"createdAt":"2024-05-07T14:08:30.961Z","feeAmount":0,"feeCurrency":"EUR","filledAmount":0,"id":"536ee1dc-528a-419e-9c00-5e04c010658d","orderAmount":0.35,"orderType":"limit","postOnly":null,"price":65000.5,"side":"buy","status":"cancelled","stopPrice":0,"symbol":"BTC/EUR","timeInForce":"GTC","updatedAt":"2024-05-07T14:10:34.837Z","userId":"2bf436fc-43e6-459a-b647-6b446f72ad96"}}},"schema":{"description":"A spot order of the authenticated user.","properties":{"cancelReason":{"description":"Why the order was cancelled, `null` otherwise. It starts with a stable code:\n`CR-1` user request, `CR-2` admin request, `CR-3` order expired, `CR-4` matching engine,\n`CR-5` and `CR-6` internal error, `CR-7` self trade, `CR-8` time in force.\nBranch on the code, not on the text after it.\n","example":"CR-1: User request","nullable":true,"pattern":"^CR-[0-9]+","type":"string"},"clientOrderId":{"description":"Identifier supplied by the client when creating the order, or `null`.","example":"my-bot-order-0001","maxLength":48,"nullable":true,"type":"string"},"cost":{"description":"Value executed so far, in the quote currency. `0` until something fills.","example":0,"minimum":0,"type":"number"},"createdAt":{"description":"When the order was created.","example":"2024-05-07T14:08:30.961Z","format":"date-time","type":"string"},"feeAmount":{"description":"Fees accumulated by the order's trades, in `feeCurrency`.","example":0,"minimum":0,"type":"number"},"feeCurrency":{"description":"Currency of `feeAmount`.","example":"EUR","pattern":"^[A-Z0-9]+$","type":"string"},"filledAmount":{"description":"Part of `orderAmount` already executed, in the base currency.","example":0,"minimum":0,"type":"number"},"id":{"description":"Order identifier.","example":"536ee1dc-528a-419e-9c00-5e04c010658d","format":"uuid","type":"string"},"orderAmount":{"description":"Order size in the base currency. For a market order sent with `amountInQuote`, the base amount computed from the order book.","example":0.35,"minimum":0,"type":"number"},"orderType":{"description":"- `limit`: rests in the book at `price` or better.\n- `market`: executes immediately against the book at the best available prices.\n- `stop-limit`: stays `inactive` until the market reaches `stopPrice`, then becomes a limit order at `price`.\n","enum":["limit","stop-limit","market"],"example":"limit","type":"string"},"postOnly":{"description":"The `postOnly` flag sent on creation, or `null` when it was not sent.","example":false,"nullable":true,"type":"boolean"},"price":{"description":"Limit price in the quote currency. `0` for `market` orders.","example":65000.5,"minimum":0,"type":"number"},"side":{"description":"`buy` spends the quote currency to get the base currency; `sell` does the opposite.","enum":["buy","sell"],"example":"buy","type":"string"},"status":{"description":"- `open`: in the order book, waiting to be filled; may be partially filled.\n- `inactive`: a `stop-limit` order whose `stopPrice` has not been reached yet. It is not in the\n  order book, but it holds funds and can be cancelled.\n- `filled`: completely executed.\n- `cancelled`: cancelled by the user, by Bit2Me or by its time-in-force; see `cancelReason`.\n  It may have been partially filled before.\n","enum":["open","inactive","filled","cancelled"],"example":"open","type":"string"},"stopPrice":{"description":"Trigger price of a `stop-limit` order, in the quote currency. `0` for other order types.","example":0,"minimum":0,"type":"number"},"symbol":{"description":"Market symbol as `BASE/QUOTE`, uppercase and separated by a slash (`BTC/EUR`). The hyphenated\nform (`BTC-EUR`) is not accepted: order creation answers `400 Symbol BTC-EUR is wrong` and the\nmarket data endpoints answer `404 Market not found for symbol BTC-EUR`. The list of valid\nsymbols is `GET /v2/trading/market-config`.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"},"timeInForce":{"default":"GTC","description":"How long the order may stay in the order book before being cancelled.\n- `GTC` (good 'til cancelled), the default: rests in the book until filled or cancelled.\n- `FOK` (fill or kill): executes completely and immediately, or is cancelled without any fill.\n  Only for `limit` orders.\n- `IOC` (immediate or cancel): part of the contract but not available on Bit2Me markets; the\n  order is rejected with `412` and `errorPayload.code` `TIME_IN_FORCE_NOT_AVAILABLE`.\n\n`market` and `stop-limit` orders accept only `GTC` (`412` `TIME_IN_FORCE_INVALID` otherwise).\n","enum":["GTC","IOC","FOK"],"example":"GTC","type":"string"},"updatedAt":{"description":"Last time the order changed (a fill, a cancellation, a stop trigger).","example":"2024-05-07T14:08:30.961Z","format":"date-time","type":"string"},"userId":{"description":"Owner of the order.","example":"2bf436fc-43e6-459a-b647-6b446f72ad96","format":"uuid","type":"string"}},"type":"object"}}},"description":"The cancelled order."},"400":{"content":{"application/json":{"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"`id` is not a UUID."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The API key, signature or nonce could not be validated."},"404":{"content":{"application/json":{"example":{"error":"Not Found","errorPayload":{"code":"ORDER_NOT_FOUND"},"message":"The order with ID e97d353f-62da-462a-989a-09439ff9dfeb was not found","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":404},"schema":{"description":"Business error from the trading service. `message` is human-readable and may change; when\n`errorPayload.code` is present, branch on it instead.\n","properties":{"error":{"description":"Standard reason phrase of the status (`Bad Request`, `Not Found`, `Precondition Failed`...).","example":"Precondition Failed","type":"string"},"errorPayload":{"additionalProperties":true,"description":"Machine-readable detail. Present only on order creation, order cancellation, order trades\nand trading wallet deposits and withdrawals: `null` there when the error has no detail\n(deposits and withdrawals omit it instead). `code` identifies the error; the other\nproperties depend on it (for example `minAmount` for `ORDER_AMOUNT_LOWER_MARKET_MIN`).\n","nullable":true,"properties":{"code":{"description":"Stable error code.","example":"ORDER_AMOUNT_LOWER_MARKET_MIN","type":"string"}},"type":"object"},"message":{"description":"What went wrong, in English.","example":"The order amount can not be lower than 0.0001","type":"string"},"reqId":{"description":"Request identifier. Quote it when reporting an incident.","example":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","type":"string"},"statusCode":{"description":"Same value as the HTTP status.","example":412,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"No order with this identifier belongs to the user."},"412":{"content":{"application/json":{"examples":{"alreadyClosed":{"summary":"The order was already filled","value":{"error":"Precondition Failed","errorPayload":{"code":"DELETE_CLOSED_ORDER"},"message":"The order status was not open, so it could not be cancelled. Order ID: 536ee1dc-528a-419e-9c00-5e04c010658d","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":412}},"tooSoon":{"summary":"Cancelled too soon after creation","value":{"error":"Precondition Failed","errorPayload":{"code":"WAIT_TO_DELETE_ORDER","millisecondsToWait":3120},"message":"You have to wait 3120 milliseconds to delete this order","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":412}}},"schema":{"description":"Business error from the trading service. `message` is human-readable and may change; when\n`errorPayload.code` is present, branch on it instead.\n","properties":{"error":{"description":"Standard reason phrase of the status (`Bad Request`, `Not Found`, `Precondition Failed`...).","example":"Precondition Failed","type":"string"},"errorPayload":{"additionalProperties":true,"description":"Machine-readable detail. Present only on order creation, order cancellation, order trades\nand trading wallet deposits and withdrawals: `null` there when the error has no detail\n(deposits and withdrawals omit it instead). `code` identifies the error; the other\nproperties depend on it (for example `minAmount` for `ORDER_AMOUNT_LOWER_MARKET_MIN`).\n","nullable":true,"properties":{"code":{"description":"Stable error code.","example":"ORDER_AMOUNT_LOWER_MARKET_MIN","type":"string"}},"type":"object"},"message":{"description":"What went wrong, in English.","example":"The order amount can not be lower than 0.0001","type":"string"},"reqId":{"description":"Request identifier. Quote it when reporting an incident.","example":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","type":"string"},"statusCode":{"description":"Same value as the HTTP status.","example":412,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The order cannot be cancelled now. `errorPayload.code`:\n\n- `DELETE_CLOSED_ORDER`: the order is already `filled` or `cancelled`.\n- `WAIT_TO_DELETE_ORDER`: on some markets an order cannot be cancelled during its first\n  5 seconds; `errorPayload.millisecondsToWait` says how long to wait.\n- `DELETE_ORDERS_DISABLED_TEMPORALLY`: cancellations are paused, globally or because the\n  market is `frozen`.\n- `USER_IS_ALREADY_DELETING_ORDER`: another cancellation of the same user is in progress; retry.\n"},"429":{"content":{"application/json":{"example":{"error":"Too Many Requests"},"schema":{"description":"Too many requests in a short time. The `Retry-After` header holds the seconds to wait before\nretrying.\n","properties":{"error":{"description":"Always `Too Many Requests`.","example":"Too Many Requests","type":"string"}},"required":["error"],"type":"object"}}},"description":"Rate limit exceeded. Wait the seconds in the `Retry-After` header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}}}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Cancel a trading order","tags":["Trading"],"x-product":{"spot":"Trading"}},"get":{"description":"Returns one of the authenticated user's orders. An order of another user answers `404`, the\nsame as one that does not exist.\n","parameters":[{"description":"Order identifier (UUID). A value that is not a UUID is rejected with `400`.","example":"536ee1dc-528a-419e-9c00-5e04c010658d","in":"path","name":"id","required":true,"schema":{"example":"70b89183-c7fa-4460-91ce-34d53d739868","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"partiallyFilled":{"summary":"Limit order partially filled","value":{"cancelReason":null,"clientOrderId":null,"cost":15600.12,"createdAt":"2024-05-07T14:08:30.961Z","feeAmount":15.60012,"feeCurrency":"EUR","filledAmount":0.24,"id":"536ee1dc-528a-419e-9c00-5e04c010658d","orderAmount":0.35,"orderType":"limit","postOnly":null,"price":65000.5,"side":"buy","status":"open","stopPrice":0,"symbol":"BTC/EUR","timeInForce":"GTC","updatedAt":"2024-05-07T14:09:02.310Z","userId":"2bf436fc-43e6-459a-b647-6b446f72ad96"}}},"schema":{"description":"A spot order of the authenticated user.","properties":{"cancelReason":{"description":"Why the order was cancelled, `null` otherwise. It starts with a stable code:\n`CR-1` user request, `CR-2` admin request, `CR-3` order expired, `CR-4` matching engine,\n`CR-5` and `CR-6` internal error, `CR-7` self trade, `CR-8` time in force.\nBranch on the code, not on the text after it.\n","example":"CR-1: User request","nullable":true,"pattern":"^CR-[0-9]+","type":"string"},"clientOrderId":{"description":"Identifier supplied by the client when creating the order, or `null`.","example":"my-bot-order-0001","maxLength":48,"nullable":true,"type":"string"},"cost":{"description":"Value executed so far, in the quote currency. `0` until something fills.","example":0,"minimum":0,"type":"number"},"createdAt":{"description":"When the order was created.","example":"2024-05-07T14:08:30.961Z","format":"date-time","type":"string"},"feeAmount":{"description":"Fees accumulated by the order's trades, in `feeCurrency`.","example":0,"minimum":0,"type":"number"},"feeCurrency":{"description":"Currency of `feeAmount`.","example":"EUR","pattern":"^[A-Z0-9]+$","type":"string"},"filledAmount":{"description":"Part of `orderAmount` already executed, in the base currency.","example":0,"minimum":0,"type":"number"},"id":{"description":"Order identifier.","example":"536ee1dc-528a-419e-9c00-5e04c010658d","format":"uuid","type":"string"},"orderAmount":{"description":"Order size in the base currency. For a market order sent with `amountInQuote`, the base amount computed from the order book.","example":0.35,"minimum":0,"type":"number"},"orderType":{"description":"- `limit`: rests in the book at `price` or better.\n- `market`: executes immediately against the book at the best available prices.\n- `stop-limit`: stays `inactive` until the market reaches `stopPrice`, then becomes a limit order at `price`.\n","enum":["limit","stop-limit","market"],"example":"limit","type":"string"},"postOnly":{"description":"The `postOnly` flag sent on creation, or `null` when it was not sent.","example":false,"nullable":true,"type":"boolean"},"price":{"description":"Limit price in the quote currency. `0` for `market` orders.","example":65000.5,"minimum":0,"type":"number"},"side":{"description":"`buy` spends the quote currency to get the base currency; `sell` does the opposite.","enum":["buy","sell"],"example":"buy","type":"string"},"status":{"description":"- `open`: in the order book, waiting to be filled; may be partially filled.\n- `inactive`: a `stop-limit` order whose `stopPrice` has not been reached yet. It is not in the\n  order book, but it holds funds and can be cancelled.\n- `filled`: completely executed.\n- `cancelled`: cancelled by the user, by Bit2Me or by its time-in-force; see `cancelReason`.\n  It may have been partially filled before.\n","enum":["open","inactive","filled","cancelled"],"example":"open","type":"string"},"stopPrice":{"description":"Trigger price of a `stop-limit` order, in the quote currency. `0` for other order types.","example":0,"minimum":0,"type":"number"},"symbol":{"description":"Market symbol as `BASE/QUOTE`, uppercase and separated by a slash (`BTC/EUR`). The hyphenated\nform (`BTC-EUR`) is not accepted: order creation answers `400 Symbol BTC-EUR is wrong` and the\nmarket data endpoints answer `404 Market not found for symbol BTC-EUR`. The list of valid\nsymbols is `GET /v2/trading/market-config`.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"},"timeInForce":{"default":"GTC","description":"How long the order may stay in the order book before being cancelled.\n- `GTC` (good 'til cancelled), the default: rests in the book until filled or cancelled.\n- `FOK` (fill or kill): executes completely and immediately, or is cancelled without any fill.\n  Only for `limit` orders.\n- `IOC` (immediate or cancel): part of the contract but not available on Bit2Me markets; the\n  order is rejected with `412` and `errorPayload.code` `TIME_IN_FORCE_NOT_AVAILABLE`.\n\n`market` and `stop-limit` orders accept only `GTC` (`412` `TIME_IN_FORCE_INVALID` otherwise).\n","enum":["GTC","IOC","FOK"],"example":"GTC","type":"string"},"updatedAt":{"description":"Last time the order changed (a fill, a cancellation, a stop trigger).","example":"2024-05-07T14:08:30.961Z","format":"date-time","type":"string"},"userId":{"description":"Owner of the order.","example":"2bf436fc-43e6-459a-b647-6b446f72ad96","format":"uuid","type":"string"}},"type":"object"}}},"description":"The order."},"400":{"content":{"application/json":{"example":{"errors":[{"code":"INVALID_REQUEST_PARAMETER","errors":[{"code":"PATTERN","message":"String does not match pattern ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$: invalid-id"}],"in":"path","message":"Invalid parameter (id): Value failed JSON Schema validation","name":"id"}],"message":"Validation errors"},"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"`id` is not a UUID."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The API key, signature or nonce could not be validated."},"404":{"content":{"application/json":{"example":{"error":"Not Found","message":"The ID e97d353f-62da-462a-989a-09439ff9dfeb was not found","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":404},"schema":{"description":"Business error from the trading service. `message` is human-readable and may change; when\n`errorPayload.code` is present, branch on it instead.\n","properties":{"error":{"description":"Standard reason phrase of the status (`Bad Request`, `Not Found`, `Precondition Failed`...).","example":"Precondition Failed","type":"string"},"errorPayload":{"additionalProperties":true,"description":"Machine-readable detail. Present only on order creation, order cancellation, order trades\nand trading wallet deposits and withdrawals: `null` there when the error has no detail\n(deposits and withdrawals omit it instead). `code` identifies the error; the other\nproperties depend on it (for example `minAmount` for `ORDER_AMOUNT_LOWER_MARKET_MIN`).\n","nullable":true,"properties":{"code":{"description":"Stable error code.","example":"ORDER_AMOUNT_LOWER_MARKET_MIN","type":"string"}},"type":"object"},"message":{"description":"What went wrong, in English.","example":"The order amount can not be lower than 0.0001","type":"string"},"reqId":{"description":"Request identifier. Quote it when reporting an incident.","example":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","type":"string"},"statusCode":{"description":"Same value as the HTTP status.","example":412,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"No order with this identifier belongs to the user."},"429":{"content":{"application/json":{"example":{"error":"Too Many Requests"},"schema":{"description":"Too many requests in a short time. The `Retry-After` header holds the seconds to wait before\nretrying.\n","properties":{"error":{"description":"Always `Too Many Requests`.","example":"Too Many Requests","type":"string"}},"required":["error"],"type":"object"}}},"description":"Rate limit exceeded. Wait the seconds in the `Retry-After` header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}}}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get a trading order","tags":["Trading"],"x-product":{"spot":"Trading"}}},"/v1/trading/order/{id}/trades":{"get":{"description":"Returns every execution (fill) of one of the authenticated user's orders, unpaginated. An\norder that has not filled yet returns an empty array.\n\nCompared with `GET /v1/trading/trade`, each trade also carries `feePercentageDiscount` and\n`spaceCenterLevelId`.\n","parameters":[{"description":"Order identifier (UUID). A value that is not a UUID is rejected with `400`.","example":"536ee1dc-528a-419e-9c00-5e04c010658d","in":"path","name":"id","required":true,"schema":{"example":"70b89183-c7fa-4460-91ce-34d53d739868","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"notFilled":{"summary":"The order has no fills yet","value":[]},"twoFills":{"summary":"A limit buy filled in two trades","value":[{"amount":0.24,"amountCurrency":"BTC","clientOrderId":null,"cost":15600.12,"costEuro":15600.12,"createdAt":"2024-05-07T14:09:02.310Z","feeAmount":15.60012,"feeCurrency":"EUR","feePercentage":0.1,"feePercentageDiscount":0,"id":"4278a86a-53e7-4997-9102-01646ae8954a","isMaker":true,"orderId":"536ee1dc-528a-419e-9c00-5e04c010658d","orderType":"limit","price":65000.5,"priceCurrency":"EUR","side":"buy","spaceCenterLevelId":null,"symbol":"BTC/EUR"},{"amount":0.11,"amountCurrency":"BTC","clientOrderId":null,"cost":7150.055,"costEuro":7150.055,"createdAt":"2024-05-07T14:11:45.020Z","feeAmount":7.150055,"feeCurrency":"EUR","feePercentage":0.1,"feePercentageDiscount":0,"id":"9d3e1f2a-6b7c-4d8e-a9f0-1b2c3d4e5f60","isMaker":true,"orderId":"536ee1dc-528a-419e-9c00-5e04c010658d","orderType":"limit","price":65000.5,"priceCurrency":"EUR","side":"buy","spaceCenterLevelId":null,"symbol":"BTC/EUR"}]}},"schema":{"items":{"description":"One execution (fill) of one of the user's orders. A single order can produce several trades.","properties":{"amount":{"description":"Executed volume, in `amountCurrency` (the base currency).","example":0.35,"minimum":0,"type":"number"},"amountCurrency":{"description":"Currency of `amount`.","example":"BTC","pattern":"^[A-Z0-9]+$","type":"string"},"clientOrderId":{"description":"The `clientOrderId` sent when the order was created, or `null`.","example":"my-bot-order-0001","maxLength":48,"nullable":true,"type":"string"},"cost":{"description":"Total value of the trade in the quote currency (`price * amount`).","example":22750.175,"minimum":0,"type":"number"},"costEuro":{"description":"Total value of the trade converted to EUR at execution time.","example":22750.175,"minimum":0,"type":"number"},"createdAt":{"description":"When the trade was executed.","example":"2024-05-02T08:58:47.727Z","format":"date-time","type":"string"},"feeAmount":{"description":"Fee charged for this trade, in `feeCurrency`.","example":0.0750087,"minimum":0,"type":"number"},"feeCurrency":{"description":"Currency of `feeAmount`.","example":"EUR","pattern":"^[A-Z0-9]+$","type":"string"},"feePercentage":{"description":"Fee rate applied, as a percentage of the trade value.","example":0.3,"minimum":0,"type":"number"},"feePercentageDiscount":{"description":"Discount applied to the fee rate by the user's Space Center level, as a percentage.\nOnly returned by `GET /v1/trading/order/{id}/trades`.\n","example":0,"minimum":0,"type":"number"},"id":{"description":"Trade identifier.","example":"4278a86a-53e7-4997-9102-01646ae8954a","format":"uuid","type":"string"},"isMaker":{"description":"`true` when the user's order was resting in the book (maker), `false` when it took liquidity (taker).","example":true,"type":"boolean"},"orderId":{"description":"Order this trade belongs to.","example":"536ee1dc-528a-419e-9c00-5e04c010658d","format":"uuid","type":"string"},"orderType":{"description":"- `limit`: rests in the book at `price` or better.\n- `market`: executes immediately against the book at the best available prices.\n- `stop-limit`: stays `inactive` until the market reaches `stopPrice`, then becomes a limit order at `price`.\n","enum":["limit","stop-limit","market"],"example":"limit","type":"string"},"price":{"description":"Execution price, in `priceCurrency` (the quote currency).","example":65000.5,"minimum":0,"type":"number"},"priceCurrency":{"description":"Currency of `price` and `cost`.","example":"EUR","pattern":"^[A-Z0-9]+$","type":"string"},"side":{"description":"`buy` spends the quote currency to get the base currency; `sell` does the opposite.","enum":["buy","sell"],"example":"buy","type":"string"},"spaceCenterLevelId":{"description":"Space Center level of the user when the trade was executed, which determines\n`feePercentageDiscount`. Only returned by `GET /v1/trading/order/{id}/trades`.\n","format":"uuid","nullable":true,"type":"string"},"symbol":{"description":"Market symbol as `BASE/QUOTE`, uppercase and separated by a slash (`BTC/EUR`). The hyphenated\nform (`BTC-EUR`) is not accepted: order creation answers `400 Symbol BTC-EUR is wrong` and the\nmarket data endpoints answer `404 Market not found for symbol BTC-EUR`. The list of valid\nsymbols is `GET /v2/trading/market-config`.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"}},"type":"object"},"type":"array"}}},"description":"Trades of the order."},"400":{"content":{"application/json":{"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"`id` is not a UUID."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The API key, signature or nonce could not be validated."},"404":{"content":{"application/json":{"example":{"error":"Not Found","errorPayload":null,"message":"The ID e97d353f-62da-462a-989a-09439ff9dfeb was not found","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":404},"schema":{"description":"Business error from the trading service. `message` is human-readable and may change; when\n`errorPayload.code` is present, branch on it instead.\n","properties":{"error":{"description":"Standard reason phrase of the status (`Bad Request`, `Not Found`, `Precondition Failed`...).","example":"Precondition Failed","type":"string"},"errorPayload":{"additionalProperties":true,"description":"Machine-readable detail. Present only on order creation, order cancellation, order trades\nand trading wallet deposits and withdrawals: `null` there when the error has no detail\n(deposits and withdrawals omit it instead). `code` identifies the error; the other\nproperties depend on it (for example `minAmount` for `ORDER_AMOUNT_LOWER_MARKET_MIN`).\n","nullable":true,"properties":{"code":{"description":"Stable error code.","example":"ORDER_AMOUNT_LOWER_MARKET_MIN","type":"string"}},"type":"object"},"message":{"description":"What went wrong, in English.","example":"The order amount can not be lower than 0.0001","type":"string"},"reqId":{"description":"Request identifier. Quote it when reporting an incident.","example":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","type":"string"},"statusCode":{"description":"Same value as the HTTP status.","example":412,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"No order with this identifier belongs to the user."},"429":{"content":{"application/json":{"example":{"error":"Too Many Requests"},"schema":{"description":"Too many requests in a short time. The `Retry-After` header holds the seconds to wait before\nretrying.\n","properties":{"error":{"description":"Always `Too Many Requests`.","example":"Too Many Requests","type":"string"}},"required":["error"],"type":"object"}}},"description":"Rate limit exceeded. Wait the seconds in the `Retry-After` header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}}}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"List trades for an order","tags":["Trading"],"x-product":{"spot":"Trading"}}},"/v1/trading/trade":{"get":{"description":"Returns the authenticated user's trades (fills), filtered and paginated, together with the\ntotal number of trades that match the filters.\n\nAt most 50 trades are returned per call: a larger `limit` is silently reduced to 50. Use\n`total` and `offset` to walk the remaining pages.\n","parameters":[{"description":"Comma-separated trade identifiers, up to 20. Any value that is not a UUID is rejected with `400`.","in":"query","name":"ids","schema":{"example":"4278a86a-53e7-4997-9102-01646ae8954a","type":"string"}},{"description":"Only trades of this market, as `BASE/QUOTE`.","in":"query","name":"symbol","schema":{"description":"Market symbol as `BASE/QUOTE`, uppercase and separated by a slash (`BTC/EUR`). The hyphenated\nform (`BTC-EUR`) is not accepted: order creation answers `400 Symbol BTC-EUR is wrong` and the\nmarket data endpoints answer `404 Market not found for symbol BTC-EUR`. The list of valid\nsymbols is `GET /v2/trading/market-config`.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"}},{"description":"Only trades of orders of this side.","in":"query","name":"side","schema":{"description":"`buy` spends the quote currency to get the base currency; `sell` does the opposite.","enum":["buy","sell"],"example":"buy","type":"string"}},{"description":"Only trades of orders of this type.","in":"query","name":"orderType","schema":{"description":"- `limit`: rests in the book at `price` or better.\n- `market`: executes immediately against the book at the best available prices.\n- `stop-limit`: stays `inactive` until the market reaches `stopPrice`, then becomes a limit order at `price`.\n","enum":["limit","stop-limit","market"],"example":"limit","type":"string"}},{"description":"Only trades executed at or after this date (ISO 8601). `startTime` and `endTime` must be\nsent together, and `startTime` must not be later than `endTime`; otherwise `400`.\n","in":"query","name":"startTime","schema":{"example":"2024-05-01T00:00:00.000Z","format":"date-time","type":"string"}},{"description":"Only trades executed at or before this date (ISO 8601). Sent together with `startTime`.","in":"query","name":"endTime","schema":{"example":"2024-05-31T23:59:59.999Z","format":"date-time","type":"string"}},{"description":"Page size. Default and maximum `50`; larger values are reduced to `50`.","in":"query","name":"limit","schema":{"default":50,"example":20,"maximum":50,"minimum":1,"type":"number"}},{"description":"Number of trades to skip.","in":"query","name":"offset","schema":{"default":0,"example":0,"minimum":0,"type":"number"}},{"description":"Trade field to sort by, for example `createdAt`.","in":"query","name":"sort","schema":{"example":"createdAt","type":"string"}},{"description":"Sort direction.","in":"query","name":"direction","schema":{"enum":["asc","desc"],"example":"desc","type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"page":{"summary":"First page of a filtered query","value":{"data":[{"amount":0.24,"amountCurrency":"BTC","clientOrderId":null,"cost":15600.12,"costEuro":15600.12,"createdAt":"2024-05-07T14:09:02.310Z","feeAmount":15.60012,"feeCurrency":"EUR","feePercentage":0.1,"id":"4278a86a-53e7-4997-9102-01646ae8954a","isMaker":true,"orderId":"536ee1dc-528a-419e-9c00-5e04c010658d","orderType":"limit","price":65000.5,"priceCurrency":"EUR","side":"buy","symbol":"BTC/EUR"}],"total":12}},"withoutMatches":{"summary":"No trade matches the filters","value":{"data":[],"total":0}}},"schema":{"properties":{"data":{"description":"The trades of this page.","items":{"description":"One execution (fill) of one of the user's orders. A single order can produce several trades.","properties":{"amount":{"description":"Executed volume, in `amountCurrency` (the base currency).","example":0.35,"minimum":0,"type":"number"},"amountCurrency":{"description":"Currency of `amount`.","example":"BTC","pattern":"^[A-Z0-9]+$","type":"string"},"clientOrderId":{"description":"The `clientOrderId` sent when the order was created, or `null`.","example":"my-bot-order-0001","maxLength":48,"nullable":true,"type":"string"},"cost":{"description":"Total value of the trade in the quote currency (`price * amount`).","example":22750.175,"minimum":0,"type":"number"},"costEuro":{"description":"Total value of the trade converted to EUR at execution time.","example":22750.175,"minimum":0,"type":"number"},"createdAt":{"description":"When the trade was executed.","example":"2024-05-02T08:58:47.727Z","format":"date-time","type":"string"},"feeAmount":{"description":"Fee charged for this trade, in `feeCurrency`.","example":0.0750087,"minimum":0,"type":"number"},"feeCurrency":{"description":"Currency of `feeAmount`.","example":"EUR","pattern":"^[A-Z0-9]+$","type":"string"},"feePercentage":{"description":"Fee rate applied, as a percentage of the trade value.","example":0.3,"minimum":0,"type":"number"},"feePercentageDiscount":{"description":"Discount applied to the fee rate by the user's Space Center level, as a percentage.\nOnly returned by `GET /v1/trading/order/{id}/trades`.\n","example":0,"minimum":0,"type":"number"},"id":{"description":"Trade identifier.","example":"4278a86a-53e7-4997-9102-01646ae8954a","format":"uuid","type":"string"},"isMaker":{"description":"`true` when the user's order was resting in the book (maker), `false` when it took liquidity (taker).","example":true,"type":"boolean"},"orderId":{"description":"Order this trade belongs to.","example":"536ee1dc-528a-419e-9c00-5e04c010658d","format":"uuid","type":"string"},"orderType":{"description":"- `limit`: rests in the book at `price` or better.\n- `market`: executes immediately against the book at the best available prices.\n- `stop-limit`: stays `inactive` until the market reaches `stopPrice`, then becomes a limit order at `price`.\n","enum":["limit","stop-limit","market"],"example":"limit","type":"string"},"price":{"description":"Execution price, in `priceCurrency` (the quote currency).","example":65000.5,"minimum":0,"type":"number"},"priceCurrency":{"description":"Currency of `price` and `cost`.","example":"EUR","pattern":"^[A-Z0-9]+$","type":"string"},"side":{"description":"`buy` spends the quote currency to get the base currency; `sell` does the opposite.","enum":["buy","sell"],"example":"buy","type":"string"},"spaceCenterLevelId":{"description":"Space Center level of the user when the trade was executed, which determines\n`feePercentageDiscount`. Only returned by `GET /v1/trading/order/{id}/trades`.\n","format":"uuid","nullable":true,"type":"string"},"symbol":{"description":"Market symbol as `BASE/QUOTE`, uppercase and separated by a slash (`BTC/EUR`). The hyphenated\nform (`BTC-EUR`) is not accepted: order creation answers `400 Symbol BTC-EUR is wrong` and the\nmarket data endpoints answer `404 Market not found for symbol BTC-EUR`. The list of valid\nsymbols is `GET /v2/trading/market-config`.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"}},"type":"object"},"maxItems":50,"type":"array"},"total":{"description":"Number of trades matching the filters, across all pages.","example":12,"minimum":0,"type":"integer"}},"required":["total","data"],"type":"object"}}},"description":"The page of trades and the total count."},"400":{"content":{"application/json":{"examples":{"invalidId":{"summary":"An entry of `ids` is not a UUID","value":{"error":"Bad Request","message":"Invalid trade id: 123","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":400}},"invalidRange":{"summary":"`startTime` later than `endTime`","value":{"error":"Bad Request","message":"startTime date must be less or equal than endTime date","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":400}}},"schema":{"oneOf":[{"description":"Business error from the trading service. `message` is human-readable and may change; when\n`errorPayload.code` is present, branch on it instead.\n","properties":{"error":{"description":"Standard reason phrase of the status (`Bad Request`, `Not Found`, `Precondition Failed`...).","example":"Precondition Failed","type":"string"},"errorPayload":{"additionalProperties":true,"description":"Machine-readable detail. Present only on order creation, order cancellation, order trades\nand trading wallet deposits and withdrawals: `null` there when the error has no detail\n(deposits and withdrawals omit it instead). `code` identifies the error; the other\nproperties depend on it (for example `minAmount` for `ORDER_AMOUNT_LOWER_MARKET_MIN`).\n","nullable":true,"properties":{"code":{"description":"Stable error code.","example":"ORDER_AMOUNT_LOWER_MARKET_MIN","type":"string"}},"type":"object"},"message":{"description":"What went wrong, in English.","example":"The order amount can not be lower than 0.0001","type":"string"},"reqId":{"description":"Request identifier. Quote it when reporting an incident.","example":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","type":"string"},"statusCode":{"description":"Same value as the HTTP status.","example":412,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"},{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}]}}},"description":"A filter is malformed. The body is a `TradingErrorResponse` for the checks made by the\ntrading service (`ids`, dates), or a `RequestValidationErrorResponse` when a parameter does\nnot match its declared type.\n"},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The API key, signature or nonce could not be validated."},"429":{"content":{"application/json":{"example":{"error":"Too Many Requests"},"schema":{"description":"Too many requests in a short time. The `Retry-After` header holds the seconds to wait before\nretrying.\n","properties":{"error":{"description":"Always `Too Many Requests`.","example":"Too Many Requests","type":"string"}},"required":["error"],"type":"object"}}},"description":"Rate limit exceeded. Wait the seconds in the `Retry-After` header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}}}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"List user trades","tags":["Trading"],"x-product":{"spot":"Trading"}}},"/v1/trading/trade/last":{"get":{"description":"Returns the most recent public trades of a market, newest first, as compact positional tuples\n`[side, price, amount, timestamp]`. No authentication is required.\n\nAt most 50 trades are returned; a larger `limit` is silently reduced to 50. For a live feed\nuse the trading websocket instead of polling.\n","parameters":[{"description":"Market as `BASE/QUOTE`.","in":"query","name":"symbol","required":true,"schema":{"description":"Market symbol as `BASE/QUOTE`, uppercase and separated by a slash (`BTC/EUR`). The hyphenated\nform (`BTC-EUR`) is not accepted: order creation answers `400 Symbol BTC-EUR is wrong` and the\nmarket data endpoints answer `404 Market not found for symbol BTC-EUR`. The list of valid\nsymbols is `GET /v2/trading/market-config`.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"}},{"description":"Number of trades. Default and maximum `50`; larger values are reduced to `50`.","in":"query","name":"limit","schema":{"default":50,"example":20,"maximum":50,"minimum":1,"type":"number"}}],"responses":{"200":{"content":{"application/json":{"example":[["sell",63606.3,0.0008,1715087548704],["buy",63601.2,0.0013,1715087523417]],"schema":{"items":{"description":"One public trade as a positional tuple `[side, price, amount, timestamp]`:\n`side` is `buy` or `sell`, `price` is in the quote currency, `amount` in the\nbase currency, and `timestamp` is the execution time in Unix epoch milliseconds.\n","example":["sell",63606.3,0.0008,1715087548704],"items":{"oneOf":[{"enum":["buy","sell"],"type":"string"},{"type":"number"}]},"maxItems":4,"minItems":4,"type":"array"},"type":"array"}}},"description":"The latest trades of the market."},"400":{"content":{"application/json":{"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"`symbol` was not sent."},"404":{"content":{"application/json":{"example":{"error":"Not Found","message":"Market not found for symbol BTC-EUR","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":404},"schema":{"description":"Business error from the trading service. `message` is human-readable and may change; when\n`errorPayload.code` is present, branch on it instead.\n","properties":{"error":{"description":"Standard reason phrase of the status (`Bad Request`, `Not Found`, `Precondition Failed`...).","example":"Precondition Failed","type":"string"},"errorPayload":{"additionalProperties":true,"description":"Machine-readable detail. Present only on order creation, order cancellation, order trades\nand trading wallet deposits and withdrawals: `null` there when the error has no detail\n(deposits and withdrawals omit it instead). `code` identifies the error; the other\nproperties depend on it (for example `minAmount` for `ORDER_AMOUNT_LOWER_MARKET_MIN`).\n","nullable":true,"properties":{"code":{"description":"Stable error code.","example":"ORDER_AMOUNT_LOWER_MARKET_MIN","type":"string"}},"type":"object"},"message":{"description":"What went wrong, in English.","example":"The order amount can not be lower than 0.0001","type":"string"},"reqId":{"description":"Request identifier. Quote it when reporting an incident.","example":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","type":"string"},"statusCode":{"description":"Same value as the HTTP status.","example":412,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"No market with this symbol exists."}},"summary":"Get last trades","tags":["Trading"],"x-product":{"spot":"MarketData"}}},"/v1/trading/wallet/balance":{"get":{"description":"Returns the balances of the authenticated user's trading (Pro) wallets, one entry per\ncurrency wallet. Only these funds can be used to place orders; move funds in\nand out with `POST /v1/trading/wallet/deposit` and `POST /v1/trading/wallet/withdraw`.\n\n`blockedBalance` includes both the funds reserved by open orders and the funds assigned to\nthe user's trading bots.\n","parameters":[{"description":"Comma-separated currency codes. Only those wallets are returned; all of them when omitted.","in":"query","name":"symbols","schema":{"example":"BTC,EUR","pattern":"^[A-Z0-9]+(,[A-Z0-9]+)*$","type":"string"}},{"description":"`number` (default) returns `balance` and `blockedBalance` as JSON numbers, as always.\n`string` returns them as exact decimal strings with up to 18 decimals, in plain notation\nand without trailing zeros (for example `\"8.084941303345199\"`).\n","in":"query","name":"amountFormat","schema":{"default":"number","enum":["number","string"],"example":"string","type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"none":{"summary":"The user has no trading wallet yet","value":[]},"numbers":{"summary":"Default format, amounts as JSON numbers","value":[{"balance":0.35,"blockedBalance":0,"createdAt":"2023-09-13T14:05:42.149Z","currency":"BTC","id":"ec7c234e-b6c0-4c13-b458-b613f3c608f1","manualFunds":false,"userId":"2bf436fc-43e6-459a-b647-6b446f72ad96"},{"balance":1250.5,"blockedBalance":22750.18,"createdAt":"2023-09-13T14:05:42.149Z","currency":"EUR","id":"3a9f1c2d-7e4b-4f6a-8c1d-2b3e4f5a6b7c","manualFunds":false,"userId":"2bf436fc-43e6-459a-b647-6b446f72ad96"}]},"strings":{"summary":"With `amountFormat=string`, amounts as exact decimal strings","value":[{"balance":"8.084941303345199","blockedBalance":"0","createdAt":"2023-09-13T14:05:42.149Z","currency":"BTC","id":"ec7c234e-b6c0-4c13-b458-b613f3c608f1","manualFunds":false,"userId":"2bf436fc-43e6-459a-b647-6b446f72ad96"}]}},"schema":{"items":{"description":"Balance of one currency in the user's trading (Pro) wallet.","properties":{"balance":{"description":"Amount available to place new orders or to withdraw. A JSON number by default, or an\nexact decimal string with `amountFormat=string`.\n","example":0.35,"oneOf":[{"minimum":0,"type":"number"},{"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}]},"blockedBalance":{"description":"Amount not available: reserved by open orders or assigned to the user's trading bots.\nSame format as `balance`.\n","example":0,"oneOf":[{"minimum":0,"type":"number"},{"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}]},"createdAt":{"description":"When the wallet was created.","example":"2023-09-13T14:05:42.149Z","format":"date-time","type":"string"},"currency":{"description":"Currency code of the wallet.","example":"BTC","pattern":"^[A-Z0-9]+$","type":"string"},"id":{"description":"Trading wallet identifier. It is the `walletId` of the movements of this currency.","example":"ec7c234e-b6c0-4c13-b458-b613f3c608f1","format":"uuid","type":"string"},"manualFunds":{"description":"`true` for currencies whose funds are managed manually by Bit2Me (for example `USD`).\nDeposits and withdrawals of these currencies through the API are rejected with `412`.\n","example":false,"type":"boolean"},"userId":{"description":"Owner of the wallet.","example":"2bf436fc-43e6-459a-b647-6b446f72ad96","format":"uuid","type":"string"}},"required":["id","userId","currency","balance","blockedBalance","createdAt","manualFunds"],"type":"object"},"type":"array"}}},"description":"Trading wallets of the user; an empty array when they have none."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The API key, signature or nonce could not be validated."},"429":{"content":{"application/json":{"example":{"error":"Too Many Requests"},"schema":{"description":"Too many requests in a short time. The `Retry-After` header holds the seconds to wait before\nretrying.\n","properties":{"error":{"description":"Always `Too Many Requests`.","example":"Too Many Requests","type":"string"}},"required":["error"],"type":"object"}}},"description":"Rate limit exceeded. Wait the seconds in the `Retry-After` header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}}}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"List trading wallet balances","tags":["Trading"],"x-product":{"spot":"Funding"}}},"/v1/trading/wallet/deposit":{"post":{"description":"Moves funds from the user's Bit2Me wallet into their trading wallet, where they become\navailable to place orders. The funds are taken from the user's pocket of `currency` with the\nhighest balance, which must hold at least `amount`. The transfer is recorded as a `deposit`\nmovement (`GET /v1/trading/movement`), and the trading wallet of the currency is created on\nthe first deposit.\n\nOnly one movement per currency can be in progress at a time.\n","requestBody":{"content":{"application/json":{"example":{"amount":"100","currency":"EUR"},"schema":{"properties":{"amount":{"allOf":[{"maxLength":50,"minLength":1,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}],"description":"Amount to move, as a decimal string, in `currency`. Must be greater than zero.","example":"100"},"currency":{"allOf":[{"type":"string"}],"description":"Currency code of the funds to move.","example":"EUR","pattern":"^[A-Z0-9]+$"},"fromPocketId":{"allOf":[{"example":"70b89183-c7fa-4460-91ce-34d53d739868","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}],"deprecated":true,"description":"Ignored. The pocket of `currency` with the highest balance is always used."}},"required":["amount","currency"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"balance":1350.5,"blockedBalance":0,"createdAt":"2023-09-13T14:05:42.149Z","currency":"EUR","id":"3a9f1c2d-7e4b-4f6a-8c1d-2b3e4f5a6b7c","rawBalance":"1350.5","rawBlockedBalance":"0","userId":"2bf436fc-43e6-459a-b647-6b446f72ad96"},"schema":{"description":"Trading wallet after a deposit or a withdrawal, with the balances already updated. Unlike\n`GET /v1/trading/wallet/balance` it does not carry `manualFunds`, and it adds `rawBalance`\nand `rawBlockedBalance`.\n","properties":{"balance":{"description":"Available amount after the operation.","example":1350.5,"minimum":0,"type":"number"},"blockedBalance":{"description":"Amount reserved by open orders.","example":0,"minimum":0,"type":"number"},"createdAt":{"description":"When the wallet was created.","example":"2023-09-13T14:05:42.149Z","format":"date-time","type":"string"},"currency":{"description":"Currency code of the wallet.","example":"EUR","pattern":"^[A-Z0-9]+$","type":"string"},"id":{"description":"Trading wallet identifier.","example":"3a9f1c2d-7e4b-4f6a-8c1d-2b3e4f5a6b7c","format":"uuid","type":"string"},"rawBalance":{"description":"`balance` as an exact decimal string.","example":"1350.5","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"rawBlockedBalance":{"description":"`blockedBalance` as an exact decimal string.","example":"0","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"userId":{"description":"Owner of the wallet.","example":"2bf436fc-43e6-459a-b647-6b446f72ad96","format":"uuid","type":"string"}},"required":["id","userId","currency","balance","blockedBalance","createdAt"],"type":"object"}}},"description":"The trading wallet with the deposit applied."},"400":{"content":{"application/json":{"example":{"errors":[{"code":"INVALID_REQUEST_PARAMETER","errors":[{"code":"OBJECT_MISSING_REQUIRED_PROPERTY","message":"Missing required property: currency"}],"in":"body","message":"Invalid parameter (data): Value failed JSON Schema validation","name":"data"}],"message":"Validation errors"},"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"A required field is missing or has the wrong format."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The API key, signature or nonce could not be validated."},"412":{"content":{"application/json":{"examples":{"currencyNotAllowed":{"summary":"Currency not traded on Bit2Me Pro","value":{"error":"Precondition Failed","message":"Currency XYZ not allowed","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":412}},"disabled":{"summary":"Deposits paused by Bit2Me","value":{"error":"Precondition Failed","errorPayload":{"code":"DEPOSITS_DISABLED_TEMPORALLY"},"message":"Deposits have been disabled temporally","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":412}},"noPocket":{"summary":"The user has no pocket of the currency","value":{"error":"Precondition Failed","message":"The pocket is not associated to the user","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":412}},"pendingMovement":{"summary":"A previous movement is still in progress","value":{"error":"Precondition Failed","message":"There is already a pending movement for currency EUR","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":412}},"pocketBalance":{"summary":"Not enough funds in the pocket","value":{"error":"Precondition Failed","message":"The balance of the pocket is lower than the deposit amount","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":412}}},"schema":{"description":"Business error from the trading service. `message` is human-readable and may change; when\n`errorPayload.code` is present, branch on it instead.\n","properties":{"error":{"description":"Standard reason phrase of the status (`Bad Request`, `Not Found`, `Precondition Failed`...).","example":"Precondition Failed","type":"string"},"errorPayload":{"additionalProperties":true,"description":"Machine-readable detail. Present only on order creation, order cancellation, order trades\nand trading wallet deposits and withdrawals: `null` there when the error has no detail\n(deposits and withdrawals omit it instead). `code` identifies the error; the other\nproperties depend on it (for example `minAmount` for `ORDER_AMOUNT_LOWER_MARKET_MIN`).\n","nullable":true,"properties":{"code":{"description":"Stable error code.","example":"ORDER_AMOUNT_LOWER_MARKET_MIN","type":"string"}},"type":"object"},"message":{"description":"What went wrong, in English.","example":"The order amount can not be lower than 0.0001","type":"string"},"reqId":{"description":"Request identifier. Quote it when reporting an incident.","example":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","type":"string"},"statusCode":{"description":"Same value as the HTTP status.","example":412,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The deposit cannot be made. Only `DEPOSITS_DISABLED_TEMPORALLY` carries\n`errorPayload.code`; the rest are told apart by `message`:\n\n- `Currency \u003ccurrency\u003e not allowed`: the currency is not traded on Bit2Me Pro.\n- `Not allowed deposit with currency (\u003ccurrency\u003e)`: the currency is managed manually\n  (`manualFunds`).\n- `The amount of the deposit cannot be zero or lower`.\n- `There is already a pending movement for currency \u003ccurrency\u003e`: wait until the previous\n  movement finishes.\n- `The pocket is not associated to the user`: the user has no pocket of the currency.\n- `The balance of the pocket is lower than the deposit amount`.\n- `Error in the server updating the standard wallet`: the transfer could not be completed at\n  that moment. Check `GET /v1/trading/movement` before retrying.\n"},"429":{"content":{"application/json":{"example":{"error":"Too Many Requests"},"schema":{"description":"Too many requests in a short time. The `Retry-After` header holds the seconds to wait before\nretrying.\n","properties":{"error":{"description":"Always `Too Many Requests`.","example":"Too Many Requests","type":"string"}},"required":["error"],"type":"object"}}},"description":"Rate limit exceeded. Wait the seconds in the `Retry-After` header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}}}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Deposit into trading wallet","tags":["Trading"],"x-product":{"spot":"Funding"}}},"/v1/trading/wallet/withdraw":{"post":{"description":"Moves funds from the user's trading wallet back to their Bit2Me wallet, to the user's pocket\nof `currency` with the highest balance. Only the available `balance` can be withdrawn; funds\nreserved by open orders must be released first by cancelling those orders. The transfer is\nrecorded as a `withdrawal` movement (`GET /v1/trading/movement`).\n\n`amount` is rounded down to the decimals of the currency. Only one movement per currency can\nbe in progress at a time.\n","requestBody":{"content":{"application/json":{"examples":{"crypto":{"summary":"Withdraw bitcoin","value":{"amount":"0.1","currency":"BTC"}},"fiat":{"summary":"Withdraw euros","value":{"amount":"50","currency":"EUR"}}},"schema":{"properties":{"amount":{"allOf":[{"maxLength":50,"minLength":1,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}],"description":"Amount to move, as a decimal string, in `currency`. Must be greater than zero.","example":"50"},"currency":{"allOf":[{"type":"string"}],"description":"Currency code of the trading wallet to withdraw from.","example":"EUR","pattern":"^[A-Z0-9]+$"},"toPocketId":{"allOf":[{"example":"70b89183-c7fa-4460-91ce-34d53d739868","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}],"deprecated":true,"description":"Ignored. The pocket of `currency` with the highest balance is always used."}},"required":["amount","currency"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"balance":1300.5,"blockedBalance":0,"createdAt":"2023-09-13T14:05:42.149Z","currency":"EUR","id":"3a9f1c2d-7e4b-4f6a-8c1d-2b3e4f5a6b7c","rawBalance":"1300.5","rawBlockedBalance":"0","userId":"2bf436fc-43e6-459a-b647-6b446f72ad96"},"schema":{"description":"Trading wallet after a deposit or a withdrawal, with the balances already updated. Unlike\n`GET /v1/trading/wallet/balance` it does not carry `manualFunds`, and it adds `rawBalance`\nand `rawBlockedBalance`.\n","properties":{"balance":{"description":"Available amount after the operation.","example":1350.5,"minimum":0,"type":"number"},"blockedBalance":{"description":"Amount reserved by open orders.","example":0,"minimum":0,"type":"number"},"createdAt":{"description":"When the wallet was created.","example":"2023-09-13T14:05:42.149Z","format":"date-time","type":"string"},"currency":{"description":"Currency code of the wallet.","example":"EUR","pattern":"^[A-Z0-9]+$","type":"string"},"id":{"description":"Trading wallet identifier.","example":"3a9f1c2d-7e4b-4f6a-8c1d-2b3e4f5a6b7c","format":"uuid","type":"string"},"rawBalance":{"description":"`balance` as an exact decimal string.","example":"1350.5","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"rawBlockedBalance":{"description":"`blockedBalance` as an exact decimal string.","example":"0","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"userId":{"description":"Owner of the wallet.","example":"2bf436fc-43e6-459a-b647-6b446f72ad96","format":"uuid","type":"string"}},"required":["id","userId","currency","balance","blockedBalance","createdAt"],"type":"object"}}},"description":"The trading wallet with the withdrawal applied."},"400":{"content":{"application/json":{"example":{"errors":[{"code":"INVALID_REQUEST_PARAMETER","errors":[{"code":"OBJECT_MISSING_REQUIRED_PROPERTY","message":"Missing required property: amount"}],"in":"body","message":"Invalid parameter (data): Value failed JSON Schema validation","name":"data"}],"message":"Validation errors"},"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"A required field is missing or has the wrong format."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The API key, signature or nonce could not be validated."},"412":{"content":{"application/json":{"examples":{"disabled":{"summary":"Withdrawals paused by Bit2Me","value":{"error":"Precondition Failed","errorPayload":{"code":"WITHDRAWS_DISABLED_TEMPORALLY"},"message":"Withdraws have been disabled temporally","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":412}},"insufficient":{"summary":"Not enough available balance","value":{"error":"Precondition Failed","message":"The balance of the trading wallet is lower than the withdraw amount","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":412}},"noWallet":{"summary":"The user never deposited this currency","value":{"error":"Precondition Failed","message":"The trading wallet for currency ADA does not exist","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":412}},"pendingMovement":{"summary":"A previous movement is still in progress","value":{"error":"Precondition Failed","message":"There is already a pending movement for currency EUR","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":412}}},"schema":{"description":"Business error from the trading service. `message` is human-readable and may change; when\n`errorPayload.code` is present, branch on it instead.\n","properties":{"error":{"description":"Standard reason phrase of the status (`Bad Request`, `Not Found`, `Precondition Failed`...).","example":"Precondition Failed","type":"string"},"errorPayload":{"additionalProperties":true,"description":"Machine-readable detail. Present only on order creation, order cancellation, order trades\nand trading wallet deposits and withdrawals: `null` there when the error has no detail\n(deposits and withdrawals omit it instead). `code` identifies the error; the other\nproperties depend on it (for example `minAmount` for `ORDER_AMOUNT_LOWER_MARKET_MIN`).\n","nullable":true,"properties":{"code":{"description":"Stable error code.","example":"ORDER_AMOUNT_LOWER_MARKET_MIN","type":"string"}},"type":"object"},"message":{"description":"What went wrong, in English.","example":"The order amount can not be lower than 0.0001","type":"string"},"reqId":{"description":"Request identifier. Quote it when reporting an incident.","example":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","type":"string"},"statusCode":{"description":"Same value as the HTTP status.","example":412,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The withdrawal cannot be made. Only `WITHDRAWS_DISABLED_TEMPORALLY` carries\n`errorPayload.code`; the rest are told apart by `message`:\n\n- `The amount of the withdraw cannot be zero or lower`.\n- `The trading wallet for currency \u003ccurrency\u003e does not exist` (or `Trading wallet of\n  currency \u003ccurrency\u003e not found`): the user never deposited this currency.\n- `The balance of the trading wallet is lower than the withdraw amount`: only the available\n  `balance` counts.\n- `Not allowed withdraw with currency (\u003ccurrency\u003e)`: the currency is managed manually\n  (`manualFunds`).\n- `There is already a pending movement for currency \u003ccurrency\u003e`: wait until the previous\n  movement finishes.\n- `Error in the server updating the standard wallet`: the transfer could not be completed at\n  that moment. Check `GET /v1/trading/movement` before retrying.\n"},"429":{"content":{"application/json":{"example":{"error":"Too Many Requests"},"schema":{"description":"Too many requests in a short time. The `Retry-After` header holds the seconds to wait before\nretrying.\n","properties":{"error":{"description":"Always `Too Many Requests`.","example":"Too Many Requests","type":"string"}},"required":["error"],"type":"object"}}},"description":"Rate limit exceeded. Wait the seconds in the `Retry-After` header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}}}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Withdraw from trading wallet","tags":["Trading"],"x-product":{"spot":"Funding"}}},"/v1/trading/working-capital":{"get":{"description":"Returns the working capital limits configured for the authenticated user: how much of each\ncurrency Bit2Me may top up automatically into the trading wallet over a rolling 24-hour\nwindow, and how much of it has been used. Users without working capital get an empty array.\n","parameters":[{"description":"Comma-separated currency codes. Only those limits are returned; all of them when omitted.","in":"query","name":"symbols","schema":{"example":"B2M,EUR","pattern":"^[A-Z0-9]+(,[A-Z0-9]+)*$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"configured":{"summary":"One currency with working capital","value":[{"currency":"B2M","limit":5000,"refillThreshold":2500,"remaining":2500,"type":"deposit","used":2500}]},"none":{"summary":"No working capital configured","value":[]}},"schema":{"items":{"description":"Working capital limit of one currency over a rolling 24-hour window.","properties":{"currency":{"description":"Currency code the limit applies to.","example":"B2M","pattern":"^[A-Z0-9]+$","type":"string"},"limit":{"description":"Maximum working capital amount allowed in the rolling 24-hour window.","example":5000,"minimum":0,"type":"number"},"refillThreshold":{"description":"Trading wallet balance below which an automatic working capital refill is made.","example":2500,"minimum":0,"type":"number"},"remaining":{"description":"Amount still available in the current window (`limit - used`, never below `0`).","example":2500,"minimum":0,"type":"number"},"type":{"description":"Kind of movement the limit applies to. Only deposit limits exist.","enum":["deposit"],"example":"deposit","type":"string"},"used":{"description":"Working capital amount deposited in the last 24 hours.","example":2500,"minimum":0,"type":"number"}},"required":["currency","type","limit","used","remaining","refillThreshold"],"type":"object"},"type":"array"}}},"description":"Working capital limits of the user."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"The API key, signature or nonce could not be validated."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"List working capital limits","tags":["Trading"],"x-product":{"spot":"Funding"}}},"/v1/verifier/subaccount/file":{"get":{"description":"Downloads an identity verification file (document image or selfie) for a\nspecific subaccount. The response is the raw binary file.\n","parameters":[{"description":"Type of identity file to download.","in":"query","name":"identityFileType","required":true,"schema":{"enum":["backDocument","frontDocument","selfie","livenessFrontDocument","livenessBackDocument","livenessSelfie"],"type":"string"}},{"description":"Identifier of the subaccount.","in":"query","name":"subAccountId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/octet-stream":{"schema":{"format":"binary","type":"string"}}},"description":"The identity file binary content."},"403":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Invalid credentials or user not authorized."},"404":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"User or file not found."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Download subaccount identity file","tags":["Verifier"],"x-product":{"wallet":"KYC"}}},"/v1/wallet/pocket":{"delete":{"description":"Deletes one of the user's pockets. It must be empty, must not be the user's last pocket of\nthat asset, and must have no active recurring orders. A deleted pocket no longer appears in\n`GET /v1/wallet/pocket`.\n","parameters":[{"description":"Pocket to delete.","in":"query","name":"id","required":true,"schema":{"description":"Pocket identifier, as returned by `GET /v1/wallet/pocket`.","example":"eb775a29-365d-4881-b7b9-1fa66fe1eb4d","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"result":true},"schema":{"properties":{"result":{"type":"boolean"}},"required":["result"],"type":"object"}}},"description":"The pocket was deleted."},"400":{"content":{"application/json":{"example":{"errors":[{"code":"INVALID_REQUEST_PARAMETER","errors":[{"code":"REQUIRED","message":"Value is required but was not provided","path":[]}],"in":"query","message":"Invalid parameter (id): Value is required but was not provided","name":"id"}],"message":"Validation errors"},"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"`id` is missing or not a lowercase UUID."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"example":{"data":{},"error":"Not Found","message":"pocket not found","statusCode":404},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The user has no pocket with this `id`."},"412":{"content":{"application/json":{"examples":{"lastPocket":{"summary":"The user's only pocket of that asset","value":{"data":{},"error":"Precondition Failed","message":"can not delete last pocket","statusCode":412}},"notEmpty":{"summary":"The pocket still holds funds","value":{"data":{},"error":"Precondition Failed","message":"pocket not empty","statusCode":412}},"recurringOrders":{"summary":"The pocket has active recurring orders","value":{"data":{},"error":"Precondition Failed","message":"Can not delete pocket with active recurring orders","statusCode":412}}},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The pocket cannot be deleted: `Can not delete pocket with active recurring orders`,\n`can not delete last pocket` (the user's only pocket of that asset) or\n`pocket not empty`.\n"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Delete a pocket","tags":["Wallet"],"x-product":{"wallet":"Wallet"}},"get":{"description":"Returns the authenticated user's pockets, the wallet accounts that hold one asset each. A\nuser can have several pockets of the same asset. Deleted pockets are not listed.\n\nWithout `id` every pocket is returned, sorted by balance, highest first. With `id` the\nresponse is an array with that single pocket, or `404` when the user has no such pocket.\n","parameters":[{"description":"Pocket to return. When omitted, all the user's pockets are returned.","in":"query","name":"id","schema":{"description":"Pocket identifier, as returned by `GET /v1/wallet/pocket`.","example":"eb775a29-365d-4881-b7b9-1fa66fe1eb4d","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"all":{"summary":"All the user's pockets","value":[{"balance":"1250.50000000","blockedBalance":"0.00000000","blockedOutputBalance":"0.00000000","color":0,"createdAt":"2023-05-10T08:21:37.512Z","currency":"EUR","id":"9ca6cf96-4645-4658-b086-6cdb367c16bd","name":"Euro pocket"},{"balance":"0.04217534","blockedBalance":"0.00000000","blockedOutputBalance":"0.00000000","color":3,"createdAt":"2023-05-10T08:22:05.034Z","currency":"BTC","id":"eb775a29-365d-4881-b7b9-1fa66fe1eb4d","name":"Bitcoin savings"}]},"one":{"summary":"A single pocket, requested with id","value":[{"balance":"0.04217534","blockedBalance":"0.00000000","blockedOutputBalance":"0.00000000","color":3,"createdAt":"2023-05-10T08:22:05.034Z","currency":"BTC","id":"eb775a29-365d-4881-b7b9-1fa66fe1eb4d","name":"Bitcoin savings"}]}},"schema":{"items":{"description":"A pocket, a wallet account of the user that holds one asset.","properties":{"balance":{"description":"Funds available to operate with, as a decimal string padded to the precision of the asset.","example":"0.04217534","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"blockedBalance":{"description":"Funds of the pocket that are blocked and cannot be used, as a decimal string.","example":"0.00000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"blockedOutputBalance":{"description":"Funds already leaving the pocket in an operation that is still being executed, as a decimal string.","example":"0.00000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"color":{"description":"Colour index of the pocket, from `0` to `15`, used by the Bit2Me apps to tell pockets apart.","example":3,"maximum":15,"minimum":0,"type":"integer"},"createdAt":{"description":"When the pocket was created (ISO 8601).","example":"2023-05-10T08:22:05.034Z","format":"date-time","type":"string"},"currency":{"description":"Asset the pocket holds.","example":"BTC","type":"string"},"id":{"description":"Pocket identifier, as returned by `GET /v1/wallet/pocket`.","example":"eb775a29-365d-4881-b7b9-1fa66fe1eb4d","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"},"name":{"description":"Name the user gave to the pocket, between 1 and 255 characters.","example":"Bitcoin savings","maxLength":255,"minLength":1,"type":"string"}},"required":["id","name","color","currency","balance","blockedBalance","createdAt"],"type":"object"},"type":"array"}}},"description":"The pockets, sorted by balance, highest first."},"400":{"content":{"application/json":{"example":{"errors":[{"code":"INVALID_REQUEST_PARAMETER","errors":[{"code":"PATTERN","message":"String does not match pattern ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$: nope","params":["^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","nope"],"path":[]}],"in":"query","message":"Invalid parameter (id): Value failed JSON Schema validation","name":"id"}],"message":"Validation errors"},"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"`id` is not a lowercase UUID."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"example":{"data":{},"error":"Not Found","message":"pocket not found","statusCode":404},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"`id` was sent and the user has no pocket with it."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"List the user's pockets, or get one","tags":["Wallet"],"x-product":{"wallet":"Wallet"}},"post":{"description":"Creates a new, empty pocket of an asset for the user. Any crypto asset can be used; the only\nfiat currency allowed is `EUR`.\n\nThe number of pockets is limited, both per asset and per week; reaching either limit answers\n`406`.\n\nThe `4xx` bodies other than `400` field validation carry a copy of the whole error in\n`data`.\n","requestBody":{"content":{"application/json":{"examples":{"crypto":{"summary":"A Bitcoin pocket","value":{"color":3,"currency":"BTC","name":"Bitcoin savings"}},"euro":{"summary":"A second euro pocket, with the default colour","value":{"currency":"EUR","name":"Holidays"}}},"schema":{"properties":{"color":{"allOf":[{"description":"Colour index of the pocket, from `0` to `15`, used by the Bit2Me apps to tell pockets apart.","example":3,"maximum":15,"minimum":0,"type":"integer"}],"default":0,"description":"Colour index of the pocket, from `0` to `15`. `0` when omitted."},"currency":{"description":"Asset the pocket will hold. Fiat currencies other than `EUR` are rejected.","example":"BTC","type":"string"},"name":{"allOf":[{"description":"Name the user gave to the pocket, between 1 and 255 characters.","example":"Bitcoin savings","maxLength":255,"minLength":1,"type":"string"}],"description":"Name of the pocket, between 1 and 255 characters."}},"required":["currency","name"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"id":"4c8e2a6f-1b3d-4f5a-9c7e-0d2b4f6a8c1e"},"schema":{"properties":{"id":{"allOf":[{"description":"Pocket identifier, as returned by `GET /v1/wallet/pocket`.","example":"eb775a29-365d-4881-b7b9-1fa66fe1eb4d","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}],"description":"Identifier of the new pocket."}},"required":["id"],"type":"object"}}},"description":"The pocket was created."},"400":{"content":{"application/json":{"examples":{"invalidCurrency":{"summary":"Unknown asset, or fiat other than EUR","value":{"data":{"data":{},"error":"Bad Request","message":"currency is not valid","statusCode":400},"error":"Bad Request","message":"currency is not valid","statusCode":400}},"missingName":{"summary":"name missing","value":{"errors":[{"code":"INVALID_REQUEST_PARAMETER","errors":[{"code":"OBJECT_MISSING_REQUIRED_PROPERTY","message":"Missing required property: name","params":["name"],"path":[]}],"in":"body","message":"Invalid parameter (data): Value failed JSON Schema validation","name":"data"}],"message":"Validation errors"}}},"schema":{"oneOf":[{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"},{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}]}}},"description":"The body does not match the contract (`RequestValidationErrorResponse`), or `currency` is\nunknown or a fiat currency other than `EUR` (`currency is not valid`).\n"},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"406":{"content":{"application/json":{"examples":{"perAsset":{"summary":"Maximum number of pockets of this asset","value":{"data":{"data":{},"error":"Not Acceptable","message":"pocket limit reached","statusCode":406},"error":"Not Acceptable","message":"pocket limit reached","statusCode":406}},"perWeek":{"summary":"Maximum number of pockets created this week","value":{"data":{"data":{},"error":"Not Acceptable","message":"weekly pocket limit reached","statusCode":406},"error":"Not Acceptable","message":"weekly pocket limit reached","statusCode":406}}},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"A pocket limit was reached: `pocket limit reached` for the maximum per asset, or\n`weekly pocket limit reached` for the maximum created per week.\n"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Create a pocket","tags":["Wallet"],"x-product":{"wallet":"Wallet"}}},"/v1/wallet/settings/assets":{"get":{"description":"Returns, for each asset the wallet supports, the operations it allows: deposits,\nwithdrawals, transfers, buys, sells, swaps and Earn. Use it to decide which actions to offer\nfor an asset: an operation that is not listed for an asset is not available for it.\n\nIt does not need authentication.\n","responses":{"200":{"content":{"application/json":{"example":[{"actions":["deposit","withdrawal","transfer","purchase","instant-buy","instant-sell","instant-swap","earn-deposit","earn-withdrawal"],"symbol":"BTC"},{"actions":["deposit","withdrawal","transfer","instant-buy","instant-sell","instant-swap"],"symbol":"EUR"},{"actions":["deposit","withdrawal","transfer","instant-buy","instant-sell","instant-swap"],"symbol":"XRP"}],"schema":{"items":{"properties":{"actions":{"description":"Operations the wallet allows with the asset. Empty when it allows none.","example":["deposit","withdrawal","transfer","instant-buy","instant-sell","instant-swap"],"items":{"description":"An operation the wallet allows with an asset:\n\n- `deposit`: receive the asset in a pocket. `deposit-app` and `deposit-web` restrict it to\n  the Bit2Me app or to the web.\n- `withdrawal`: send the asset out of Bit2Me, to a blockchain address or a bank account.\n- `transfer`: send the asset to another pocket or to another Bit2Me user.\n- `purchase`: buy the asset with an external payment method, such as a card.\n- `instant-buy`, `instant-sell`, `instant-swap`: buy it, sell it or swap it with another\n  asset between pockets. `instant` is the former value covering the three.\n- `earn-deposit`, `earn-withdrawal`: move it to Earn and back. `earn` is the former value\n  covering both.\n\nNew values may appear with new products, so ignore the ones you do not know.\n","enum":["deposit","deposit-app","deposit-web","earn","earn-deposit","earn-withdrawal","instant","instant-buy","instant-sell","instant-swap","purchase","transfer","withdrawal"],"example":"withdrawal","type":"string"},"type":"array","uniqueItems":true},"symbol":{"description":"Symbol of the asset.","example":"BTC","type":"string"}},"required":["symbol","actions"],"type":"object"},"type":"array"}}},"description":"The supported assets, each with the operations it allows."}},"summary":"List the wallet operations allowed per asset","tags":["Wallet"],"x-product":{"wallet":"Wallet"}}},"/v1/wallet/transaction":{"post":{"description":"Executes a proforma created with `POST /v1/wallet/transaction/proforma`, with exactly the\namounts it quoted, and creates the transaction. The proforma must belong to the user and\nmust not have expired; otherwise the answer is `404`.\n\n**Second factor.** Withdrawals to a blockchain address, transfers to another user and bank\nwithdrawals need the user's second factor in the `x-totp` header, with its kind in\n`x-totp-type`. Without it, or with a code that is not accepted, the call answers `420` and\nnothing is executed; repeat the call with the code. For some assets the first `420` also\nstarts the confirmation of the operation, as `data` says. Social Pay payments may also ask\nfor these headers.\n\nThe user needs at least the basic (Express) identity verification level, except for the\nPro trading account operations.\n\nThe body of the `200` depends on the kind of proforma:\n\n- Operations between pockets, withdrawals and buys paid from a pocket: `{ \"id\": ... }`, the\n  identifier of the transaction created.\n- Buys with an external payment method (card, Google Pay, Apple Pay, PayPal, Hub Latam):\n  `executed`, whether the payment was executed, and when it was, the `tellerId` of the\n  payment order, its `provider` and a `token` of the payment.\n- Launchpad purchases paid from a pocket: `{ \"id\": ..., \"enqueued\": true }`, as they are\n  completed shortly after.\n- Pro trading account operations and Social Pay payments: the result of the operation in\n  that product.\n","parameters":[{"description":"The user's second-factor code, for the operations that need it (see the description).\nIgnored by the other operations.\n","in":"header","name":"x-totp","schema":{"example":"123456","pattern":"^[0-9]{4,6}$","type":"string"}},{"description":"Kind of second factor `x-totp` comes from, for instance `gauth` for an authenticator app.","in":"header","name":"x-totp-type","schema":{"enum":["gauth","email","sms","call","whatsapp"],"example":"gauth","type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"buyWithNote":{"summary":"Execute a buy proforma and keep a note on it","value":{"note":"Monthly savings","proforma":"3f6c2a1e-8b7d-4e5f-9a0b-1c2d3e4f5a6b"}},"paypal":{"summary":"Execute a PayPal buy proforma","value":{"params":{"paypal":{"clientMetadataId":"example-client-metadata-id"}},"proforma":"2c4e6a8b-0d1f-4a3c-9e5b-7d9f1b3d5e7a"}},"withdrawal":{"summary":"Execute a withdrawal proforma","value":{"proforma":"7d9e4c21-5a3b-4f6e-8c1d-2b4a6e8f0c13"}}},"schema":{"properties":{"concept":{"allOf":[{"description":"Free text attached to a transaction, up to 100 characters.","example":"Monthly savings","maxLength":100,"type":"string"}],"description":"Description to store as the `concept` of the transaction. Used by operations\nbetween pockets, withdrawals and buys paid from a pocket.\n"},"note":{"allOf":[{"description":"Free text attached to a transaction, up to 100 characters.","example":"Monthly savings","maxLength":100,"type":"string"}],"description":"The user's private note on the transaction. Used by the same operations as\n`concept`.\n"},"params":{"description":"Extra data for the payment method of the proforma.","properties":{"paypal":{"description":"Data for buys paid with PayPal.","properties":{"clientMetadataId":{"description":"PayPal client metadata identifier of the device that makes the payment.","example":"example-client-metadata-id","minLength":1,"type":"string"}},"required":["clientMetadataId"],"type":"object"}},"type":"object"},"proforma":{"allOf":[{"description":"Proforma identifier, the `id` returned by `POST /v1/wallet/transaction/proforma`.","example":"3f6c2a1e-8b7d-4e5f-9a0b-1c2d3e4f5a6b","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}],"description":"The `id` of the proforma to execute."}},"required":["proforma"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"examples":{"externalPaymentNotExecuted":{"summary":"Buy with an external payment method that was not executed","value":{"executed":false}},"launchpad":{"summary":"Launchpad purchase paid from a pocket","value":{"enqueued":true,"id":"9b2d4f61-3c5e-4a7b-8d9f-0e1a2b3c4d5e"}},"transaction":{"summary":"Operation between pockets, withdrawal or buy paid from a pocket","value":{"id":"7d9e4c21-5a3b-4f6e-8c1d-2b4a6e8f0c13"}}},"schema":{"additionalProperties":true,"description":"Result of the execution; its fields depend on the kind of proforma.","properties":{"enqueued":{"description":"Only on Launchpad purchases paid from a pocket, always `true`.","example":true,"type":"boolean"},"executed":{"description":"Only on buys with an external payment method. Whether the payment was executed.","example":true,"type":"boolean"},"id":{"description":"Identifier of the transaction created, to use with `GET /v1/wallet/transaction/{id}`.","example":"7d9e4c21-5a3b-4f6e-8c1d-2b4a6e8f0c13","format":"uuid","type":"string"},"provider":{"description":"Only on executed buys with an external payment method. Provider that processed the payment.","example":"example-provider","type":"string"},"tellerId":{"description":"Only on executed buys with an external payment method. Identifier of the payment order.","example":"a1b2c3d4-e5f6-4890-abcd-ef1234567890","format":"uuid","type":"string"},"token":{"description":"Only on executed buys with an external payment method. Token of the payment.","example":"xxx-test-token","type":"string"}},"type":"object"}}},"description":"The proforma was executed. The shape of the body depends on the kind of proforma, as described above."},"400":{"content":{"application/json":{"examples":{"missingProforma":{"summary":"proforma missing","value":{"errors":[{"code":"INVALID_REQUEST_PARAMETER","errors":[{"code":"OBJECT_MISSING_REQUIRED_PROPERTY","message":"Missing required property: proforma","params":["proforma"],"path":[]}],"in":"body","message":"Invalid parameter (data): Value failed JSON Schema validation","name":"data"}],"message":"Validation errors"}},"purchaseProformaNotFound":{"summary":"Buy with an external payment method whose proforma is gone","value":{"data":{},"error":"Bad Request","message":"proforma transaction not found","statusCode":400}}},"schema":{"oneOf":[{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"},{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}]}}},"description":"The body does not match the contract: `proforma` missing or not a lowercase UUID, or\n`concept` or `note` longer than 100 characters. Buys with an external payment method can\nalso answer `400` with `WalletErrorResponse`, for instance `proforma transaction not found`.\n"},"401":{"content":{"application/json":{"example":{"data":{},"error":"Unauthorized","message":"Low verification tier for userId: 2bf436fc-43e6-459a-b647-6b446f72ad96. Actual tier: 0. Minimum expected tier: 1","statusCode":401},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The user's identity verification level is below the basic (Express) level."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"example":{"data":{},"error":"Not Found","message":"proforma not found","statusCode":404},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The proforma does not exist, has expired or belongs to another user (`proforma not found`\nor `proforma transaction not found`), or its pocket no longer exists\n(`pocket not found`). Request a new proforma.\n"},"409":{"content":{"application/json":{"example":{"data":{},"error":"Conflict","message":"invalid proforma 7d9e4c21-5a3b-4f6e-8c1d-2b4a6e8f0c13","statusCode":409},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The proforma cannot be executed with this operation (`invalid proforma \u003cid\u003e`). Request a new one."},"412":{"content":{"application/json":{"example":{"data":{"code":"not-enough-funds"},"error":"Precondition Failed","message":"could not update pocket/not enough funds","statusCode":412},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The source pocket no longer has the funds the proforma needs, for instance because the\nbalance changed after the proforma was created (`not enough funds` or\n`could not update pocket/not enough funds`). `data.code` is `not-enough-funds`.\n"},"420":{"content":{"application/json":{"examples":{"confirmationStarted":{"summary":"The confirmation of the operation was started","value":{"data":{"retryIntervalSeconds":60,"sfaProcessInitialized":true,"sfaType":"email"},"error":"Unknown","message":"two-factor athentication TOTP token mismatch","statusCode":420}},"missingOrWrongCode":{"summary":"x-totp missing or not accepted","value":{"data":{},"error":"Unknown","message":"two-factor athentication TOTP token mismatch","statusCode":420}}},"schema":{"description":"The operation needs the user's second factor and it was missing or not accepted. Nothing was\nexecuted.\n","properties":{"data":{"description":"Empty for most operations. For some assets, the first request without a code starts the\nconfirmation of the operation, and `data` says so.\n","properties":{"retryIntervalSeconds":{"description":"Seconds to wait before asking for a new code.","example":60,"minimum":0,"type":"integer"},"sfaProcessInitialized":{"description":"Whether the confirmation of the operation was started and a code can now be sent.","example":true,"type":"boolean"},"sfaType":{"description":"Kind of second factor to send in `x-totp-type` when repeating the request.","example":"email","type":"string"}},"type":"object"},"error":{"description":"Reason phrase of the HTTP status. `Unknown`, as `420` has no standard name.","example":"Unknown","type":"string"},"message":{"description":"Fixed text, always `two-factor athentication TOTP token mismatch` (with that spelling).","example":"two-factor athentication TOTP token mismatch","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","enum":[420],"example":420,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The operation needs the second factor and `x-totp` was missing or not accepted. Nothing\nwas executed.\n"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Execute a proforma","tags":["Wallet"],"x-product":{"wallet":"Wallet"}}},"/v1/wallet/transaction/proforma":{"post":{"description":"Prices an operation without executing it and returns a proforma: the exact amounts each side\nwill move, the fees and the rates, valid until `expirationTime`. Execute it with\n`POST /v1/wallet/transaction`, sending its `id` as `proforma`; an expired proforma cannot be\nexecuted and has to be requested again.\n\nWhat the operation is depends on the fields sent:\n\n- **Between own pockets** (no `operation`): `pocket` (or `currency`) as source and\n  `destination.pocket` or `destination.currency` as destination. The same asset is a\n  transfer; from fiat to crypto a buy, from crypto to fiat a sell, between two cryptos a\n  swap. Conversions between two fiat currencies are rejected.\n- **Buy or sell by market** (`operation` `buy` or `sell` with `pair`, and no `pocket` or\n  `destination`): the pockets of both assets are used, and created if the user has none.\n- **Withdrawal to a blockchain address** (no `operation`): `destination.address` with\n  `destination.network`, and `destination.tag` or `queryParams` on networks that need a\n  memo.\n- **Withdrawal to a bank account** (no `operation`): `destination.bankAccount` from a fiat\n  pocket.\n- **Buy with an external payment method** (`operation` `purchase`): `origin` says how to pay\n  and `destination.pocket` or `destination.currency` where the asset goes.\n- **Social Pay** (`operation` `social-payment`): `pocket` and one of `destination.email`,\n  `destination.phone` or `destination.alias`.\n- **Launchpad** (`operation` `launchpad-purchase`): a `pocket` or an `origin` payment\n  method, and the Launchpad sale in `destination.launchpad`.\n\n`amount` is expressed in `currency`. With `type` `REA` (the default, except for `purchase`)\nthe destination receives exactly `amount` and the fees are added to what the origin pays;\nwith `SEA` (the default for `purchase`) the origin pays exactly `amount` and the fees are\ntaken from what the destination receives.\n\nThe user needs at least the basic (Express) identity verification level, except for the\nPro trading account operations, and the complete level for recurring operations (any\n`frequency` other than `punctual`).\n\nThe `4xx` bodies other than `400` field validation and `403` carry a copy of the whole error\nin `data`, so their details are under `data.data`.\n","requestBody":{"content":{"application/json":{"examples":{"bankWithdrawal":{"summary":"Withdraw 100 EUR to a bank account","value":{"amount":"100","currency":"EUR","destination":{"bankAccount":{"bankAccount":"ES0000000000000000000000","country":"ES","receiverName":"Jane Doe"}},"pocket":"9ca6cf96-4645-4658-b086-6cdb367c16bd"}},"buy":{"summary":"Spend exactly 100 EUR on BTC","value":{"amount":"100","currency":"EUR","operation":"buy","pair":"BTC/EUR","type":"SEA","userCurrency":"EUR"}},"cardPurchase":{"summary":"Buy BTC for 50 EUR with a saved card","value":{"amount":"50","currency":"EUR","destination":{"currency":"BTC"},"operation":"purchase","origin":{"creditcard":{"cardId":"5fc2c058-c4a3-4b41-980c-761ec4324be9"}}}},"recurringBuy":{"summary":"First execution of a weekly buy of ETH from the euro pocket","value":{"amount":"25","currency":"EUR","destination":{"currency":"ETH"},"frequency":"weekly","isInitialRecurringOrder":true,"pocket":"9ca6cf96-4645-4658-b086-6cdb367c16bd"}},"withdrawal":{"summary":"Send exactly 0.01 BTC to an external address","value":{"amount":"0.01","currency":"BTC","destination":{"address":"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq","network":"bitcoin"},"pocket":"eb775a29-365d-4881-b7b9-1fa66fe1eb4d"}}},"schema":{"properties":{"amount":{"allOf":[{"maxLength":50,"minLength":1,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}],"description":"Amount of the operation, as a decimal string expressed in `currency`. Must be\ngreater than 0. Whether it is what the origin pays or what the destination\nreceives depends on `type`.\n","example":"100"},"concept":{"allOf":[{"description":"Free text attached to a transaction, up to 100 characters.","example":"Monthly savings","maxLength":100,"type":"string"}],"description":"Description of the transaction, stored as its `concept`."},"currency":{"description":"Currency `amount` is expressed in, which can differ from the asset of the source\npocket (it is converted). When `pocket` is omitted it also selects the source\npocket.\n","example":"EUR","type":"string"},"destination":{"description":"Where the funds go. Send the one field that identifies it (`pocket`, `currency`,\n`address`, `bankAccount`, `email`, `phone`, `alias` or `launchpad`), plus\n`network` and `tag` with an `address`.\n","properties":{"address":{"description":"Blockchain address to withdraw to, together with `network`. It must be a\nvalid address of that network for the asset of the source pocket.\n","example":"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq","type":"string"},"alias":{"description":"Alias of the receiver, for `social-payment`.","example":"janedoe","type":"string"},"bankAccount":{"description":"Bank account to withdraw to, from a fiat pocket.","properties":{"bankAccount":{"description":"Account number, usually an IBAN.","example":"ES0000000000000000000000","minLength":1,"type":"string"},"bankAddress":{"description":"Address of the bank.","example":"1 Example Street, Madrid","type":"string"},"bankBranch":{"description":"Bank branch, in the countries that use one.","example":"0000","type":"string"},"bankCode":{"description":"Bank code, in the countries that use one.","example":"0000","type":"string"},"bankName":{"description":"Name of the bank.","example":"Example Bank","type":"string"},"country":{"description":"Country of the bank account, for instance `ES`.","example":"ES","minLength":1,"type":"string"},"receiverName":{"description":"Name of the holder of the account.","example":"Jane Doe","type":"string"},"swiftCode":{"description":"SWIFT/BIC code of the bank.","example":"EXAMESMMXXX","type":"string"},"taxDocument":{"description":"Tax identification document of the holder, in the countries that require it.","example":"00000000T","type":"string"}},"required":["bankAccount","country"],"type":"object"},"currency":{"description":"Asset to receive, when the destination is the user's pocket of that asset\nrather than a specific pocket.\n","example":"BTC","type":"string"},"email":{"allOf":[{"format":"email","maxLength":96,"minLength":6,"type":"string"}],"description":"Email of the receiver, for `social-payment`.","example":"jane.doe@example.com"},"launchpad":{"description":"Launchpad sale to buy in, for `launchpad-purchase`.","example":"8e2f4a6c-1b3d-4e5f-9a7b-0c2d4e6f8a1b","format":"uuid","type":"string"},"network":{"description":"Network id of `address`, for instance `bitcoin`, `ethereum` or `xrpLedger`.\nAn unknown network is rejected.\n","example":"bitcoin","type":"string"},"phone":{"allOf":[{"properties":{"countryCode":{"pattern":"^[0-9]{1,4}$","type":"string"},"number":{"maxLength":32,"pattern":"^[0-9]+$","type":"string"}},"required":["number","countryCode"],"type":"object"}],"description":"Phone of the receiver, for `social-payment`."},"pocket":{"allOf":[{"description":"Pocket identifier, as returned by `GET /v1/wallet/pocket`.","example":"eb775a29-365d-4881-b7b9-1fa66fe1eb4d","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}],"description":"Destination pocket of the user."},"tag":{"description":"Destination tag or memo for `address`, on networks that need one.","example":"123456","type":"string"}},"type":"object"},"frequency":{"description":"`punctual` for a one-off operation, or how often a recurring order repeats it.\nAnything other than `punctual` needs the complete verification level.\n","enum":["punctual","daily","weekly","monthly"],"example":"punctual","type":"string"},"isInitialRecurringOrder":{"description":"Marks the operation as the first execution of a recurring order.","example":false,"type":"boolean"},"note":{"allOf":[{"description":"Free text attached to a transaction, up to 100 characters.","example":"Monthly savings","maxLength":100,"type":"string"}],"description":"The user's private note on the transaction, as later returned by\n`GET /v1/wallet/transaction/{id}`.\n"},"operation":{"description":"Special flow to use; omit it for operations between pockets and for withdrawals.\nSee the description of the operation for what each value needs.\n","enum":["purchase","social-payment","launchpad-purchase","buy","sell"],"example":"buy","type":"string"},"origin":{"description":"External payment method, for `purchase` and `launchpad-purchase`. Send exactly\none of `creditcard`, `hubLatam`, `googlePay`, `applePay` or `paypal`.\n","properties":{"applePay":{"description":"Send `apple-pay` to pay with Apple Pay.","enum":["apple-pay"],"example":"apple-pay","type":"string"},"creditcard":{"description":"Pay with one of the user's saved cards.","properties":{"cardId":{"description":"Identifier of the saved card to charge.","example":"5fc2c058-c4a3-4b41-980c-761ec4324be9","format":"uuid","type":"string"}},"required":["cardId"],"type":"object"},"googlePay":{"description":"Send `google-pay` to pay with Google Pay.","enum":["google-pay"],"example":"google-pay","type":"string"},"hubLatam":{"description":"Pay with a Latin American local payment method.","properties":{"paymentMethod":{"description":"Local payment method to use, for instance `pix`.","example":"pix","type":"string"}},"required":["paymentMethod"],"type":"object"},"params":{"description":"Extra data for the payment method.","properties":{"paypalId":{"description":"Identifier of the user's PayPal payment method.","example":"6bcf1502-5a69-498e-9dc2-6a91bb4ae8dc","format":"uuid","type":"string"}},"type":"object"},"paypal":{"description":"Send `paypal` to pay with PayPal.","enum":["paypal"],"example":"paypal","type":"string"}},"type":"object"},"pair":{"description":"Market for `buy` and `sell`, as `BASE/QUOTE`. With `buy` the user pays in QUOTE and\nreceives BASE; with `sell`, pays in BASE and receives QUOTE. Only with those two\noperations.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"},"pocket":{"allOf":[{"description":"Pocket identifier, as returned by `GET /v1/wallet/pocket`.","example":"eb775a29-365d-4881-b7b9-1fa66fe1eb4d","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}],"description":"Source pocket. When omitted, the user's pocket of `currency` is used, and created\nif there is none. Must not be sent with `buy` or `sell`.\n"},"queryParams":{"additionalProperties":{"maxLength":16,"minLength":1,"type":"string"},"description":"Memo of the destination address, as a map, for withdrawals to an address on\nnetworks that need one. Only the keys `destination_tag`, `destinationTag`,\n`memo_id` and `memoId` are accepted, each with a non-empty value.\n","example":{"memoId":"123456"},"type":"object"},"receiverName":{"description":"Kept for compatibility. The holder of the bank account of a withdrawal goes in\n`destination.bankAccount.receiverName`.\n","example":"Jane Doe","type":"string"},"type":{"description":"`REA` (Receive Exact Amount): the destination receives `amount` and the fees are\nadded on the origin. `SEA` (Send Exact Amount): the origin pays `amount` and the\nfees are taken from the destination. Defaults to `REA`, or to `SEA` for\n`purchase`.\n","enum":["REA","SEA"],"example":"SEA","type":"string"},"userCurrency":{"description":"Currency to value the proforma in, for instance the user's display currency.\nWhen sent, the response gets `userAmount` at the top level and on each side,\nand, unless it is `EUR`, a `userRate` with the value of one unit of it in EUR.\nWhen omitted, none of these are added.\n","example":"EUR","type":"string"}},"required":["amount","currency"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"examples":{"buy":{"summary":"Buy of BTC for exactly 100 EUR, fee taken from the BTC received","value":{"denomination":{"amount":"100.00000000","currency":"EUR","rate":{"extraDecimals":"0","pair":{"base":"EUR","quote":"EUR"},"value":"1.00000000"}},"destination":{"amount":"0.00178266","currency":"BTC","rate":{"extraDecimals":"0","pair":{"base":"BTC","quote":"EUR"},"value":"55535.00000000"},"userAmount":{"amount":"99.00002310","currency":"EUR"}},"expirationTime":"2024-03-28T13:06:24.032Z","fee":{"flip":{"amount":"1.00000000","currency":"EUR","percentage":"0.0100"}},"flip":{"rate":{"extraDecimals":"0","pair":{"base":"BTC","quote":"EUR"},"value":"55535.00000000"}},"id":"3f6c2a1e-8b7d-4e5f-9a0b-1c2d3e4f5a6b","method":"pocket","origin":{"amount":"100.00000000","currency":"EUR","rate":{"extraDecimals":"0","pair":{"base":"EUR","quote":"EUR"},"value":"1.00000000"},"userAmount":{"amount":"100.00000000","currency":"EUR"}},"slippageAlertPercentage":0.07,"subtype":"purchase","type":"transfer","userAmount":{"amount":"100.00000000","currency":"EUR"}}},"withdrawal":{"summary":"Withdrawal of exactly 0.01 BTC, network fee added on the origin","value":{"denomination":{"amount":"0.01000000","currency":"BTC","rate":{"extraDecimals":"0","pair":{"base":"BTC","quote":"BTC"},"value":"1.00000000"}},"destination":{"amount":"0.01000000","currency":"BTC","rate":{"extraDecimals":"0","pair":{"base":"BTC","quote":"EUR"},"value":"55535.00000000"}},"expirationTime":"2024-03-27T09:17:44.120Z","fee":{"network":{"amount":"0.00002000","currency":"BTC"}},"id":"7d9e4c21-5a3b-4f6e-8c1d-2b4a6e8f0c13","method":"blockchain","origin":{"amount":"0.01002000","currency":"BTC","rate":{"extraDecimals":"0","pair":{"base":"BTC","quote":"EUR"},"value":"55535.00000000"}},"subtype":"automatic-send","type":"withdrawal"}}},"schema":{"description":"A quote for an operation, valid until `expirationTime`. Nothing has moved yet: pass `id` as\n`proforma` to `POST /v1/wallet/transaction` to execute it with exactly these amounts.\n","properties":{"benefit":{"description":"Benefit of the user's loyalty level applied to the operation, paid as extra amount at the\ndestination. Only present when the user's level grants one.\n","properties":{"amount":{"description":"Extra amount the destination receives, as a decimal string.","example":"0.00000429","type":"string"},"currency":{"description":"Asset the benefit is paid in, the destination asset.","example":"BTC","type":"string"},"levelId":{"description":"Identifier of the loyalty level that grants the benefit.","example":"d140c42a-be88-4987-8c3d-38635124ec69","type":"string"},"percentage":{"description":"Percentage of the fee covered by the benefit.","example":50,"maximum":100,"minimum":0,"type":"number"},"quantity":{"description":"Extra amount granted by the level, as a decimal string, when it grants a fixed one.","example":"0.00000429","type":"string"},"tier":{"description":"Loyalty level that grants the benefit.","example":"gold","nullable":true,"type":"string"}},"type":"object"},"company":{"description":"Only on bank withdrawals: the amount the bank account will receive, in the currency of\nthe Bit2Me entity that serves the user, with the rate used.\n","properties":{"destination":{"description":"Amount the bank account will receive.","properties":{"amount":{"description":"Amount paid out, as a decimal string.","example":"100.00000000","type":"string"},"currency":{"description":"Currency the withdrawal is paid out in.","example":"EUR","type":"string"},"rate":{"allOf":[{"description":"How much of `pair.quote` one unit of `pair.base` is worth.","properties":{"extraDecimals":{"description":"Number of decimal places `value` carries beyond the usual precision of `pair.quote`, as\nan integer string. `'0'` except for assets whose price is too small for that precision.\n","example":"0","pattern":"^[0-9]+$","type":"string"},"pair":{"description":"Which two assets the rate relates.","properties":{"base":{"description":"Asset being valued.","example":"BTC","type":"string"},"quote":{"description":"Asset the value is expressed in.","example":"EUR","type":"string"}},"required":["base","quote"],"type":"object"},"value":{"description":"The rate, as a decimal string. It already includes the `extraDecimals` decimals.","example":"55535.00000000","type":"string"}},"required":["value","pair"],"type":"object"}],"description":"Rate used to convert the withdrawn amount into `currency`."}},"type":"object"}},"type":"object"},"denomination":{"description":"The `amount` and `currency` of the request, with the rate between that currency and the\ncurrency of the origin pocket. When both are the same the rate is `1`.\n","properties":{"amount":{"description":"The `amount` of the request, as a decimal string.","example":"100.00000000","type":"string"},"currency":{"description":"The `currency` of the request.","example":"EUR","type":"string"},"rate":{"description":"How much of `pair.quote` one unit of `pair.base` is worth.","properties":{"extraDecimals":{"description":"Number of decimal places `value` carries beyond the usual precision of `pair.quote`, as\nan integer string. `'0'` except for assets whose price is too small for that precision.\n","example":"0","pattern":"^[0-9]+$","type":"string"},"pair":{"description":"Which two assets the rate relates.","properties":{"base":{"description":"Asset being valued.","example":"BTC","type":"string"},"quote":{"description":"Asset the value is expressed in.","example":"EUR","type":"string"}},"required":["base","quote"],"type":"object"},"value":{"description":"The rate, as a decimal string. It already includes the `extraDecimals` decimals.","example":"55535.00000000","type":"string"}},"required":["value","pair"],"type":"object"}},"required":["amount","currency","rate"],"type":"object"},"destination":{"allOf":[{"description":"One side of the proforma, with the amount it will move.","properties":{"amount":{"description":"Amount this side will move, as a decimal string. On `origin` it is what leaves the source\npocket; on `destination`, what arrives.\n","example":"100.00000000","type":"string"},"currency":{"description":"Asset of this side.","example":"EUR","type":"string"},"rate":{"allOf":[{"description":"How much of `pair.quote` one unit of `pair.base` is worth.","properties":{"extraDecimals":{"description":"Number of decimal places `value` carries beyond the usual precision of `pair.quote`, as\nan integer string. `'0'` except for assets whose price is too small for that precision.\n","example":"0","pattern":"^[0-9]+$","type":"string"},"pair":{"description":"Which two assets the rate relates.","properties":{"base":{"description":"Asset being valued.","example":"BTC","type":"string"},"quote":{"description":"Asset the value is expressed in.","example":"EUR","type":"string"}},"required":["base","quote"],"type":"object"},"value":{"description":"The rate, as a decimal string. It already includes the `extraDecimals` decimals.","example":"55535.00000000","type":"string"}},"required":["value","pair"],"type":"object"}],"description":"Value of one unit of `currency` in EUR (`pair.base` is `currency`, `pair.quote` is `EUR`)."},"userAmount":{"allOf":[{"description":"An amount valued in the `userCurrency` of the request.","properties":{"amount":{"description":"The converted amount, as a decimal string.","example":"100.00000000","type":"string"},"currency":{"description":"The `userCurrency` of the request.","example":"EUR","type":"string"}},"required":["currency","amount"],"type":"object"}],"description":"`amount` valued in the `userCurrency` of the request, when it was sent."}},"required":["amount","currency"],"type":"object"}],"description":"What arrives at the destination."},"expirationTime":{"description":"When the proforma stops being executable (ISO 8601). The validity depends on the kind of\noperation: from seconds for conversions to days for some purchases.\n","example":"2024-03-28T13:07:48.032Z","format":"date-time","type":"string"},"fee":{"description":"The fees the operation will charge. Each kind is present only when it applies. With `type`\n`REA` they are added to what the origin pays; with `SEA` they are taken from what the\ndestination receives.\n","properties":{"flip":{"allOf":[{"description":"One fee, in the currency it is charged in.","properties":{"amount":{"description":"Amount charged, as a decimal string.","example":"1.00000000","type":"string"},"currency":{"description":"Asset the fee is charged in.","example":"EUR","type":"string"},"percentage":{"description":"Rate of a proportional fee, as a decimal string (`0.0100` is 1%). Only on the conversion\nfee and on the variable part of the payment fee.\n","example":"0.0100","type":"string"}},"required":["amount","currency"],"type":"object"}],"description":"Conversion fee, on operations that convert one asset into another."},"network":{"allOf":[{"description":"One fee, in the currency it is charged in.","properties":{"amount":{"description":"Amount charged, as a decimal string.","example":"1.00000000","type":"string"},"currency":{"description":"Asset the fee is charged in.","example":"EUR","type":"string"},"percentage":{"description":"Rate of a proportional fee, as a decimal string (`0.0100` is 1%). Only on the conversion\nfee and on the variable part of the payment fee.\n","example":"0.0100","type":"string"}},"required":["amount","currency"],"type":"object"}],"description":"Blockchain network fee, in the asset of the origin pocket."},"teller":{"description":"Fees of the payment, on operations paid or paid out with an external payment method.","properties":{"fixed":{"allOf":[{"description":"One fee, in the currency it is charged in.","properties":{"amount":{"description":"Amount charged, as a decimal string.","example":"1.00000000","type":"string"},"currency":{"description":"Asset the fee is charged in.","example":"EUR","type":"string"},"percentage":{"description":"Rate of a proportional fee, as a decimal string (`0.0100` is 1%). Only on the conversion\nfee and on the variable part of the payment fee.\n","example":"0.0100","type":"string"}},"required":["amount","currency"],"type":"object"}],"description":"Fixed part of the fee."},"variable":{"allOf":[{"description":"One fee, in the currency it is charged in.","properties":{"amount":{"description":"Amount charged, as a decimal string.","example":"1.00000000","type":"string"},"currency":{"description":"Asset the fee is charged in.","example":"EUR","type":"string"},"percentage":{"description":"Rate of a proportional fee, as a decimal string (`0.0100` is 1%). Only on the conversion\nfee and on the variable part of the payment fee.\n","example":"0.0100","type":"string"}},"required":["amount","currency"],"type":"object"}],"description":"Part of the fee proportional to the amount, with its `percentage`."}},"required":["fixed","variable"],"type":"object"}},"type":"object"},"flip":{"description":"Conversion applied by the operation.","properties":{"rate":{"allOf":[{"description":"How much of `pair.quote` one unit of `pair.base` is worth.","properties":{"extraDecimals":{"description":"Number of decimal places `value` carries beyond the usual precision of `pair.quote`, as\nan integer string. `'0'` except for assets whose price is too small for that precision.\n","example":"0","pattern":"^[0-9]+$","type":"string"},"pair":{"description":"Which two assets the rate relates.","properties":{"base":{"description":"Asset being valued.","example":"BTC","type":"string"},"quote":{"description":"Asset the value is expressed in.","example":"EUR","type":"string"}},"required":["base","quote"],"type":"object"},"value":{"description":"The rate, as a decimal string. It already includes the `extraDecimals` decimals.","example":"55535.00000000","type":"string"}},"required":["value","pair"],"type":"object"}],"description":"Conversion rate. A rate quoted against EUR is returned with EUR as `pair.quote`."}},"required":["rate"],"type":"object"},"frequency":{"description":"The `frequency` of the request, when it was sent.","enum":["punctual","daily","weekly","monthly"],"example":"punctual","type":"string"},"id":{"description":"Identifier of the proforma, to send as `proforma` when executing it.","example":"3f6c2a1e-8b7d-4e5f-9a0b-1c2d3e4f5a6b","format":"uuid","type":"string"},"isInitialRecurringOrder":{"description":"The `isInitialRecurringOrder` of the request, when it was sent.","example":false,"type":"boolean"},"method":{"description":"`method` the transaction will have once executed, for instance `pocket` or `blockchain`.\nSee `TransactionResponse`.\n","example":"pocket","type":"string"},"origin":{"allOf":[{"description":"One side of the proforma, with the amount it will move.","properties":{"amount":{"description":"Amount this side will move, as a decimal string. On `origin` it is what leaves the source\npocket; on `destination`, what arrives.\n","example":"100.00000000","type":"string"},"currency":{"description":"Asset of this side.","example":"EUR","type":"string"},"rate":{"allOf":[{"description":"How much of `pair.quote` one unit of `pair.base` is worth.","properties":{"extraDecimals":{"description":"Number of decimal places `value` carries beyond the usual precision of `pair.quote`, as\nan integer string. `'0'` except for assets whose price is too small for that precision.\n","example":"0","pattern":"^[0-9]+$","type":"string"},"pair":{"description":"Which two assets the rate relates.","properties":{"base":{"description":"Asset being valued.","example":"BTC","type":"string"},"quote":{"description":"Asset the value is expressed in.","example":"EUR","type":"string"}},"required":["base","quote"],"type":"object"},"value":{"description":"The rate, as a decimal string. It already includes the `extraDecimals` decimals.","example":"55535.00000000","type":"string"}},"required":["value","pair"],"type":"object"}],"description":"Value of one unit of `currency` in EUR (`pair.base` is `currency`, `pair.quote` is `EUR`)."},"userAmount":{"allOf":[{"description":"An amount valued in the `userCurrency` of the request.","properties":{"amount":{"description":"The converted amount, as a decimal string.","example":"100.00000000","type":"string"},"currency":{"description":"The `userCurrency` of the request.","example":"EUR","type":"string"}},"required":["currency","amount"],"type":"object"}],"description":"`amount` valued in the `userCurrency` of the request, when it was sent."}},"required":["amount","currency"],"type":"object"}],"description":"What leaves the source pocket."},"slippageAlertPercentage":{"description":"Only on operations that convert one asset into another. Price deviation, as a fraction\n(`0.07` is 7%), from which it is advisable to warn the user before executing the\nconversion.\n","example":0.07,"minimum":0,"type":"number"},"subtype":{"description":"`subtype` the transaction will have once executed, for instance `purchase` or `transfer`.\nSee `TransactionResponse`.\n","example":"purchase","type":"string"},"type":{"description":"`type` the transaction will have once executed.","enum":["deposit","transfer","withdrawal"],"example":"transfer","type":"string"},"userAmount":{"allOf":[{"description":"An amount valued in the `userCurrency` of the request.","properties":{"amount":{"description":"The converted amount, as a decimal string.","example":"100.00000000","type":"string"},"currency":{"description":"The `userCurrency` of the request.","example":"EUR","type":"string"}},"required":["currency","amount"],"type":"object"}],"description":"`denomination.amount` valued in the `userCurrency` of the request, when it was sent."},"userRate":{"allOf":[{"description":"Value of one unit of the `userCurrency` requested, in EUR.","properties":{"pair":{"description":"The `userCurrency` as `base` and `EUR` as `quote`.","properties":{"base":{"description":"The `userCurrency` requested.","example":"USD","type":"string"},"quote":{"description":"Always `EUR`.","example":"EUR","type":"string"}},"required":["base","quote"],"type":"object"},"value":{"description":"The rate, as a decimal string.","example":"0.92180000","type":"string"}},"required":["value","pair"],"type":"object"}],"description":"Value of one unit of `userCurrency` in EUR, when `userCurrency` was sent and is not `EUR`."}},"required":["id","expirationTime","origin","destination"],"type":"object"}}},"description":"The proforma."},"400":{"content":{"application/json":{"examples":{"fieldValidation":{"summary":"Field of the wrong type","value":{"error":"Bad Request","message":"amount must be a string","statusCode":400}},"invalidAddress":{"summary":"Address not valid for the asset and network","value":{"data":{"data":{},"error":"Bad Request","message":"invalid 0x0000000000000000000000000000000000000000 address for BTC bitcoin","statusCode":400},"error":"Bad Request","message":"invalid 0x0000000000000000000000000000000000000000 address for BTC bitcoin","statusCode":400}},"invalidInputData":{"summary":"Fields that match no flow","value":{"data":{"data":{},"error":"Bad Request","message":"invalid input data","statusCode":400},"error":"Bad Request","message":"invalid input data","statusCode":400}}},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The request is not valid. Two shapes are possible:\n\n- A field of the wrong type or outside its allowed values is rejected before anything\n  else, with a `message` that joins every failed check, for instance\n  `amount must be a string` or `type must be one of the following values: REA, SEA`.\n- The other checks answer with the details under `data`. The messages are\n  `invalid input data` (a combination of fields that matches no flow, or an unknown\n  `currency`, `pair` asset, `destination` currency or `userCurrency`), `invalid amount`\n  (not greater than 0), `pocket must be specified`, `not valid destination tag` and\n  `not valid address tag value` (`queryParams`),\n  `invalid \u003caddress\u003e address for \u003ccurrency\u003e \u003cnetwork\u003e`, `invalid transaction` (a\n  conversion between two fiat currencies), `unrecognized origin '\u003corigin\u003e'` (a\n  `purchase` whose `origin` is none of the documented payment methods),\n  `Not enough balance. \u003cdetail\u003e`, and\n  `Invalid currency: \u003cuserCurrency\u003e` when the amounts cannot be valued in it.\n"},"401":{"content":{"application/json":{"example":{"data":{"data":{},"error":"Unauthorized","message":"Low verification tier for userId: 2bf436fc-43e6-459a-b647-6b446f72ad96. Actual tier: 0. Minimum expected tier: 1","statusCode":401},"error":"Unauthorized","message":"Low verification tier for userId: 2bf436fc-43e6-459a-b647-6b446f72ad96. Actual tier: 0. Minimum expected tier: 1","statusCode":401},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The user's identity verification level is too low for the operation: the basic\n(Express) level for most operations, the complete level for recurring ones.\n"},"403":{"content":{"application/json":{"examples":{"assetBlocked":{"summary":"Operation not available for this asset","value":{"error":"Forbidden","message":"Operation not available for this asset","statusCode":403}},"invalidCredentials":{"summary":"Credentials missing or rejected","value":{"code":403,"description":"invalid credentials"}}},"schema":{"oneOf":[{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"},{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}]}}},"description":"Either the credentials were rejected (`InvalidCredentialsResponse`), or the operation is\nnot available to the user for this asset (`WalletErrorResponse`).\n"},"404":{"content":{"application/json":{"example":{"data":{"data":{},"error":"Not Found","message":"source pocket eb775a29-365d-4881-b7b9-1fa66fe1eb4d not found","statusCode":404},"error":"Not Found","message":"source pocket eb775a29-365d-4881-b7b9-1fa66fe1eb4d not found","statusCode":404},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The source or destination pocket does not exist or is not the user's."},"405":{"content":{"application/json":{"example":{"data":{"data":{},"error":"Method Not Allowed","message":"Operations between BTC and XRP are not supported","statusCode":405},"error":"Method Not Allowed","message":"Operations between BTC and XRP are not supported","statusCode":405},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The pair of assets or the payment method is not supported, for instance\n`Operations between \u003ccurrency\u003e and \u003ccurrency\u003e are not supported`.\n"},"406":{"content":{"application/json":{"example":{"data":{"data":{},"error":"Not Acceptable","message":"source and destination are the same","statusCode":406},"error":"Not Acceptable","message":"source and destination are the same","statusCode":406},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The source and the destination are the same pocket."},"412":{"content":{"application/json":{"examples":{"notEnoughFunds":{"summary":"The pocket cannot pay the amount plus fees","value":{"data":{"data":{"amount":"0.50000000","code":"not-enough-funds","currency":"BTC","fee":"0.00002000","minimumAmount":0.0001},"error":"Precondition Failed","message":"not enough funds","statusCode":412},"error":"Precondition Failed","message":"not enough funds","statusCode":412}},"proformaLimit":{"summary":"Too many proformas requested","value":{"data":{"data":{},"error":"Precondition Failed","message":"proforma limit reached","statusCode":412},"error":"Precondition Failed","message":"proforma limit reached","statusCode":412}}},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The operation cannot be prepared in the current state. The messages are\n`not enough funds` (the source pocket cannot pay the amount plus fees; `data.data` has\nthe `currency`, the `amount`, the `fee`, the `minimumAmount` of a withdrawal and\n`code: not-enough-funds`), `Not enough balance. \u003cdetail\u003e` (also with\n`code: not-enough-funds`) and `proforma limit reached` (too many proformas requested;\nwait before requesting more).\n"},"417":{"content":{"application/json":{"example":{"data":{"data":{"greaterThan":{"currency":"BTC","volume":"0.00002000"}},"error":"Expectation Failed","message":"The minimum volume for an order must be greater than 0.00002000 BTC","statusCode":417},"error":"Expectation Failed","message":"The minimum volume for an order must be greater than 0.00002000 BTC","statusCode":417},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The amount is outside the limits of the operation, for instance\n`The minimum volume for an order must be greater than \u003camount\u003e \u003ccurrency\u003e`, with the limit\nin `data.data`. A conversion larger than the market can fill also answers `417`, with\n`code: not-enough-order-book` in `data.data`.\n"},"422":{"content":{"application/json":{"example":{"data":{"data":{},"error":"Unprocessable Entity","message":"swap too big between BTC/EUR","statusCode":422},"error":"Unprocessable Entity","message":"swap too big between BTC/EUR","statusCode":422},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The conversion is too large to be quoted, for instance\n`swap too big between \u003cbase\u003e/\u003cquote\u003e`.\n"},"423":{"content":{"application/json":{"example":{"data":{"data":{},"error":"Locked","message":"This operation is blocked","statusCode":423},"error":"Locked","message":"This operation is blocked","statusCode":423},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The operation is blocked for the user."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Quote a wallet operation (create a proforma)","tags":["Wallet"],"x-product":{"wallet":"Wallet"}}},"/v1/wallet/transaction/{id}":{"get":{"description":"Returns one movement of the authenticated user's wallet, with more detail than the lists:\nthe fees, the conversion rate, the hash of the blockchain transaction, the user's note and,\nwith `userCurrency`, the amounts valued in that currency.\n\nThe user must be the sender or the receiver; any other id is answered with `404`, the same\nas an id that does not exist. A movement whose processing failed is reported here with\nstatus `pending`.\n","parameters":[{"description":"Identifier of the transaction, as returned by `GET /v3/wallet/transaction`.","in":"path","name":"id","required":true,"schema":{"example":"f040acdf-62b0-4040-9574-655fdcf7e541","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}},{"description":"Currency to value the transaction in, for instance the user's display currency. When it\nis sent, each side gets a `userAmount` with its amount valued at the date of the\nmovement, the response gets a top-level `userAmount` equal to the destination one, and,\nunless it is `EUR`, a `userRate` with the value of one unit of it in EUR today. When it\nis omitted none of these are added. An unknown currency is rejected with `400`.\n","in":"query","name":"userCurrency","schema":{"example":"EUR","minLength":1,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"buy":{"summary":"A completed buy of BTC with EUR, requested with userCurrency=EUR","value":{"canceledAt":null,"completedAt":"2024-03-28T13:06:19.411Z","concept":"","date":"2024-03-28T13:06:18.032Z","denomination":{"amount":"100.00000000","currency":"EUR","rate":{"extraDecimals":"0","pair":{"base":"EUR","quote":"EUR"},"value":"1.00000000"}},"destination":{"address":null,"addressInBlacklist":null,"addressNetwork":null,"addressTag":null,"amount":"0.00178266","class":"pocket","currency":"BTC","pocketId":"eb775a29-365d-4881-b7b9-1fa66fe1eb4d","pocketName":"Bitcoin savings","rate":{"extraDecimals":"0","pair":{"base":"BTC","quote":"EUR"},"value":"55535.00000000"},"userAmount":{"amount":"99.00002310","currency":"EUR"}},"fee":{"flip":{"amount":"1.00000000","currency":"EUR","percentage":"0.0100"}},"flip":{"rate":{"extraDecimals":"0","pair":{"base":"BTC","quote":"EUR"},"value":"55535.00000000"}},"frequency":"punctual","id":"f040acdf-62b0-4040-9574-655fdcf7e541","instantId":"2be1f76b-9332-4e96-9e58-8f9d65206b02","isInitialRecurringOrder":false,"method":"pocket","note":"Monthly savings","orders":{"brokerageId":"5d0c7b8e-2f4a-4c61-9b3e-7a1d2c4e6f80"},"origin":{"amount":"100.00000000","class":"pocket","currency":"EUR","pocketId":"9ca6cf96-4645-4658-b086-6cdb367c16bd","pocketName":"Euro pocket","rate":{"extraDecimals":"0","pair":{"base":"EUR","quote":"EUR"},"value":"1.00000000"},"userAmount":{"amount":"100.00000000","currency":"EUR"}},"status":"completed","substractFeeType":"SEA","subtype":"purchase","type":"transfer","updatedAt":"2024-03-28T13:06:19.411Z","userAmount":{"amount":"99.00002310","currency":"EUR"}}},"withdrawal":{"summary":"A blockchain withdrawal, requested without userCurrency","value":{"canceledAt":null,"completedAt":"2024-03-27T09:31:02.000Z","concept":"","date":"2024-03-27T09:12:44.120Z","destination":{"address":"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq","addressInBlacklist":false,"addressNetwork":"bitcoin","addressTag":null,"amount":"0.01000000","class":"blockchain","currency":"BTC","pocketId":null,"pocketName":null},"fee":{"network":{"amount":"0.00002000","currency":"BTC"}},"frequency":"punctual","id":"3c1f9a7e-2b4d-4e8f-9a61-7d5e0c2b8f14","isInitialRecurringOrder":false,"method":"blockchain","note":null,"origin":{"amount":"0.01002000","class":"pocket","currency":"BTC","pocketId":"eb775a29-365d-4881-b7b9-1fa66fe1eb4d","pocketName":"Bitcoin savings"},"status":"completed","substractFeeType":"REA","subtype":"automatic-send","transaction":{"confirmationCount":3,"confirmedAt":"2024-03-27T09:31:02.000Z","hash":"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"},"type":"withdrawal","updatedAt":"2024-03-27T09:31:02.000Z"}}},"schema":{"allOf":[{"description":"A movement of funds in the user's wallet, seen from the user's side.\n\n`type`, `subtype` and `method` together say what the movement was, and `origin.class` and\n`destination.class` say what each side is, which in turn tells which of their fields are\nfilled. A transfer between two different users is shown as a `withdrawal` to the sender and\nas a `deposit` to the receiver.\n\nAmounts are decimal strings padded to the precision of their currency.\n","properties":{"canceledAt":{"description":"When the transaction was cancelled (ISO 8601). `null` unless it was cancelled.","format":"date-time","nullable":true,"type":"string"},"company":{"description":"Present only on bank withdrawals: the amount paid out to the bank account, in the\ncurrency of the Bit2Me entity that serves the user, with the rate used.\n","properties":{"destination":{"description":"Amount the bank account receives.","properties":{"amount":{"description":"Amount paid out, as a decimal string.","example":"41.00000000","type":"string"},"currency":{"description":"Currency the withdrawal is paid out in.","example":"EUR","type":"string"},"rate":{"allOf":[{"description":"The exchange rate applied, expressed as how much of `pair.quote` one unit of `pair.base` was\nworth at the time.\n","properties":{"extraDecimals":{"description":"Extra decimal places `value` should be shifted by, as a decimal string. Almost always\n`'0'`; it is non-zero only for assets whose price needs more precision than `value`\nalone carries.\n","example":"0","type":"string"},"pair":{"description":"Which two assets the rate relates.","properties":{"base":{"type":"string"},"quote":{"type":"string"}},"required":["base","quote"],"type":"object"},"value":{"allOf":[{"maxLength":50,"minLength":1,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}],"description":"The rate, as a decimal string.","example":"55535.00000000"}},"required":["value","pair"],"type":"object"}],"description":"Rate used to convert the withdrawn amount into `currency`."}},"required":["currency","amount","rate"],"type":"object"}},"type":"object"},"completedAt":{"description":"When the transaction was completed (ISO 8601). `null` until it is.","example":"2024-03-28T13:06:19.411Z","format":"date-time","nullable":true,"type":"string"},"concept":{"description":"Short description of the transaction, as set when it was created. An empty string when\nnone was set, which is frequent.\n","example":"","type":"string"},"date":{"description":"When the transaction was created (ISO 8601). Lists are sorted by it, newest first.","example":"2024-03-28T13:06:18.032Z","format":"date-time","type":"string"},"denomination":{"description":"The amount and currency the user expressed the operation in when creating it (the\n`amount` and `currency` of the proforma), with the rate of that currency at the time.\nOmitted on movements that do not have one.\n","properties":{"amount":{"description":"Amount the operation was requested for, as a decimal string.","example":"100.00000000","type":"string"},"currency":{"description":"Currency `amount` is expressed in.","example":"EUR","type":"string"},"rate":{"allOf":[{"description":"The exchange rate applied, expressed as how much of `pair.quote` one unit of `pair.base` was\nworth at the time.\n","properties":{"extraDecimals":{"description":"Extra decimal places `value` should be shifted by, as a decimal string. Almost always\n`'0'`; it is non-zero only for assets whose price needs more precision than `value`\nalone carries.\n","example":"0","type":"string"},"pair":{"description":"Which two assets the rate relates.","properties":{"base":{"type":"string"},"quote":{"type":"string"}},"required":["base","quote"],"type":"object"},"value":{"allOf":[{"maxLength":50,"minLength":1,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}],"description":"The rate, as a decimal string.","example":"55535.00000000"}},"required":["value","pair"],"type":"object"}],"description":"Rate between `currency` and the currency of the origin pocket when the operation was\ncreated. When both are the same it is `1`, with that currency on both sides of `pair`.\n"}},"type":"object"},"destination":{"allOf":[{"description":"One side of a transaction, either where the funds came from (`origin`) or where they went\n(`destination`).\n\nWhich properties are filled depends on `class`. The two sides do not carry the same keys:\n\n- Both sides always have `class`, `amount` and `currency`, and usually `pocketId` and\n  `pocketName`, which are `null` when the side is not one of the user's pockets.\n- Only `destination` carries `address`, `addressNetwork`, `addressTag` and\n  `addressInBlacklist`, present and `null` when they do not apply.\n- When the counterparty was addressed by email, phone or alias, its `pocketId` and\n  `pocketName` are omitted, and `email`, `phone`, `alias` or `fullName` take their place.\n- A Launchpad destination only carries `class`, `amount`, `currency` and `rate`.\n","properties":{"address":{"description":"Blockchain address of the movement, on `destination` only. `null` when the movement has no address.","example":"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq","nullable":true,"type":"string"},"addressInBlacklist":{"description":"Whether the address is flagged as high risk. `null` when there is no address or the check\ndoes not apply.\n","example":false,"nullable":true,"type":"boolean"},"addressNetwork":{"description":"Network id the address belongs to, for instance `bitcoin`. `null` when there is no\naddress.\n","example":"bitcoin","nullable":true,"type":"string"},"addressTag":{"description":"Destination tag or memo used with the address, on networks that route deposits with one.\n`null` when there is none.\n","nullable":true,"type":"string"},"alias":{"description":"Alias the receiver was addressed by, on the `destination` of a payment sent with `class` `alias`.","example":"janedoe","nullable":true,"type":"string"},"amount":{"description":"Amount moved on this side, as a decimal string. It differs between the two sides on any\ntransaction that converts or charges a fee, so read both rather than assuming they match.\n","example":"100.00000000","type":"string"},"bankAccount":{"description":"Bank account (usually an IBAN) at this side. Present on the `origin` of bank deposits and\non the `destination` of bank withdrawals; omitted otherwise.\n","example":"ES0000000000000000000000","nullable":true,"type":"string"},"class":{"description":"What kind of endpoint this side of the transaction is, which tells you which of the other\nfields are filled:\n\n- `pocket`: one of the user's own pockets, so `pocketId` and `pocketName` are set.\n- `trading`: the user's Pro trading account. It has no pocket, so `pocketId` and\n  `pocketName` are `null`.\n- `earn`: Earn, in the same way as `trading`.\n- `blockchain`: an on-chain send or receive; the address is on `destination`.\n- `b2m`: another Bit2Me user reached through one of its Bit2Me addresses. Its pocket\n  fields are `null`.\n- `email`, `phone`, `alias`: another user addressed by email, phone or alias.\n- `bankAccount`: a bank account, on the `destination` of a bank withdrawal.\n- `launchpad`, `vesting`: a Launchpad sale or a vesting release.\n- `bcard`: the Bit2Me Card.\n- On the `origin` of a deposit, the payment method used: `card`, `bank-transfer`,\n  `google-pay`, `apple-pay`, `paypal`, `hub-latam`, `cvu`, `bizum`, `mbway`, `tikebit`,\n  `manual`, `b2m-card`, `promo-referral` or `profit-share`.\n\nNew values may appear with new products, so treat an unknown value as an opaque string.\n","enum":["pocket","trading","earn","blockchain","b2m","alias","email","phone","bankAccount","launchpad","vesting","bcard","card","bank-transfer","google-pay","apple-pay","paypal","hub-latam","cvu","bizum","mbway","tikebit","manual","b2m-card","promo-referral","profit-share"],"example":"pocket","type":"string"},"currency":{"description":"The asset moved on this side.","example":"EUR","type":"string"},"email":{"description":"Email the receiver was addressed by, on the `destination` of a payment sent with `class` `email`.","example":"jane.doe@example.com","nullable":true,"type":"string"},"fullName":{"description":"Name of the sender, on the `origin` of a payment the user received by email, phone or\nalias, and on some deposits when it is known. Omitted otherwise.\n","example":"Jane Doe","nullable":true,"type":"string"},"phone":{"allOf":[{"description":"Phone number split into country calling code and national number.","properties":{"countryCode":{"description":"Country calling code, without the leading `+`.","example":34,"maximum":999,"minimum":1,"type":"integer"},"number":{"description":"National number, without the country calling code.","example":600000000,"format":"int64","minimum":0,"type":"integer"}},"type":"object"}],"description":"Phone the receiver was addressed by, on the `destination` of a payment sent with `class` `phone`."},"pocketId":{"description":"Identifier of the pocket at this side. `null` when this side is not one of the user's pockets.","example":"9ca6cf96-4645-4658-b086-6cdb367c16bd","format":"uuid","nullable":true,"type":"string"},"pocketName":{"description":"Name of the pocket at this side, as the user named it. `null` when this side is not one\nof the user's pockets, for instance the Pro trading account or a blockchain address.\n","example":"Euro pocket","nullable":true,"type":"string"},"queryParams":{"additionalProperties":{"type":"string"},"description":"Memo sent with a withdrawal to an address, as given in `queryParams` when the proforma\nwas created. Present only on `destination`, and only when one was given.\n","example":{"memoId":"123456"},"type":"object"},"rate":{"allOf":[{"description":"The exchange rate applied, expressed as how much of `pair.quote` one unit of `pair.base` was\nworth at the time.\n","properties":{"extraDecimals":{"description":"Extra decimal places `value` should be shifted by, as a decimal string. Almost always\n`'0'`; it is non-zero only for assets whose price needs more precision than `value`\nalone carries.\n","example":"0","type":"string"},"pair":{"description":"Which two assets the rate relates.","properties":{"base":{"type":"string"},"quote":{"type":"string"}},"required":["base","quote"],"type":"object"},"value":{"allOf":[{"maxLength":50,"minLength":1,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}],"description":"The rate, as a decimal string.","example":"55535.00000000"}},"required":["value","pair"],"type":"object"}],"description":"Value of one unit of `currency` in EUR at the time of the movement (`pair.base` is\n`currency`, `pair.quote` is `EUR`). Omitted when the movement has no rate.\n"},"userAmount":{"description":"`amount` converted to the `userCurrency` requested, valued at the date of the movement.\nOnly in `GET /v1/wallet/transaction/{id}` when `userCurrency` is sent.\n","properties":{"amount":{"description":"The converted amount, as a decimal string.","example":"99.00002310","type":"string"},"currency":{"description":"The `userCurrency` requested.","example":"EUR","type":"string"}},"required":["currency","amount"],"type":"object"}},"type":"object"}],"description":"Where the funds went."},"frequency":{"description":"How often the operation repeats. `punctual` is a one-off operation; the others belong to a\nrecurring order that runs every day, week or month. Movements with no frequency are reported\nas `punctual`.\n","enum":["punctual","daily","weekly","monthly"],"example":"punctual","type":"string"},"id":{"description":"Identifier of the transaction. Use it with `GET /v1/wallet/transaction/{id}`.","example":"f040acdf-62b0-4040-9574-655fdcf7e541","format":"uuid","type":"string"},"instantId":{"description":"Identifier of the conversion order behind the movement. Present only on movements that\nconverted one asset into another, such as buys, sells and swaps.\n","example":"2be1f76b-9332-4e96-9e58-8f9d65206b02","type":"string"},"isInitialRecurringOrder":{"description":"`true` when this movement is the first execution of a recurring order, the one run when\nthe order is created. `false` otherwise.\n","example":false,"type":"boolean"},"method":{"description":"How the funds moved. For an internal movement between the user's own pockets this is `pocket`;\nfor a blockchain send or receive it is `blockchain`; the rest identify the payment instrument\nor the way the counterparty was addressed.\n","enum":["alias","apple-pay","b2m-card","bank-transfer","bizum","blockchain","card","cvu","email","google-pay","hub-latam","launchpad","manual","mbway","paypal","phone","pocket","profit-share","promo-referral","redeem","redemption","tikebit"],"example":"pocket","type":"string"},"orders":{"allOf":[{"description":"Identifiers of the orders that produced the movement, to correlate it with an order created\nthrough another Bit2Me product. Each property is present only when that kind of order exists.\n","example":{"brokerageId":"f040acdf-62b0-4040-9574-655fdcf7e541","tellerId":"a1b2c3d4-e5f6-4890-abcd-ef1234567890"},"properties":{"blockchainManagerId":{"description":"Identifier of the blockchain order behind the movement, on some on-chain sends and receives.","example":"2be1f76b-9332-4e96-9e58-8f9d65206b02","format":"uuid","type":"string"},"brokerageId":{"description":"Identifier of the brokerage order behind the movement, such as an instant buy, sell or swap.","example":"f040acdf-62b0-4040-9574-655fdcf7e541","format":"uuid","type":"string"},"tellerId":{"description":"Identifier of the payment order behind the movement, such as a card purchase or a bank\nwithdrawal. It is the value accepted by the `tellerId` filter of the transaction lists.\n","example":"a1b2c3d4-e5f6-4890-abcd-ef1234567890","format":"uuid","type":"string"}},"type":"object"}],"description":"Identifiers of the orders that produced the movement. Omitted when there is none.\n"},"origin":{"allOf":[{"description":"One side of a transaction, either where the funds came from (`origin`) or where they went\n(`destination`).\n\nWhich properties are filled depends on `class`. The two sides do not carry the same keys:\n\n- Both sides always have `class`, `amount` and `currency`, and usually `pocketId` and\n  `pocketName`, which are `null` when the side is not one of the user's pockets.\n- Only `destination` carries `address`, `addressNetwork`, `addressTag` and\n  `addressInBlacklist`, present and `null` when they do not apply.\n- When the counterparty was addressed by email, phone or alias, its `pocketId` and\n  `pocketName` are omitted, and `email`, `phone`, `alias` or `fullName` take their place.\n- A Launchpad destination only carries `class`, `amount`, `currency` and `rate`.\n","properties":{"address":{"description":"Blockchain address of the movement, on `destination` only. `null` when the movement has no address.","example":"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq","nullable":true,"type":"string"},"addressInBlacklist":{"description":"Whether the address is flagged as high risk. `null` when there is no address or the check\ndoes not apply.\n","example":false,"nullable":true,"type":"boolean"},"addressNetwork":{"description":"Network id the address belongs to, for instance `bitcoin`. `null` when there is no\naddress.\n","example":"bitcoin","nullable":true,"type":"string"},"addressTag":{"description":"Destination tag or memo used with the address, on networks that route deposits with one.\n`null` when there is none.\n","nullable":true,"type":"string"},"alias":{"description":"Alias the receiver was addressed by, on the `destination` of a payment sent with `class` `alias`.","example":"janedoe","nullable":true,"type":"string"},"amount":{"description":"Amount moved on this side, as a decimal string. It differs between the two sides on any\ntransaction that converts or charges a fee, so read both rather than assuming they match.\n","example":"100.00000000","type":"string"},"bankAccount":{"description":"Bank account (usually an IBAN) at this side. Present on the `origin` of bank deposits and\non the `destination` of bank withdrawals; omitted otherwise.\n","example":"ES0000000000000000000000","nullable":true,"type":"string"},"class":{"description":"What kind of endpoint this side of the transaction is, which tells you which of the other\nfields are filled:\n\n- `pocket`: one of the user's own pockets, so `pocketId` and `pocketName` are set.\n- `trading`: the user's Pro trading account. It has no pocket, so `pocketId` and\n  `pocketName` are `null`.\n- `earn`: Earn, in the same way as `trading`.\n- `blockchain`: an on-chain send or receive; the address is on `destination`.\n- `b2m`: another Bit2Me user reached through one of its Bit2Me addresses. Its pocket\n  fields are `null`.\n- `email`, `phone`, `alias`: another user addressed by email, phone or alias.\n- `bankAccount`: a bank account, on the `destination` of a bank withdrawal.\n- `launchpad`, `vesting`: a Launchpad sale or a vesting release.\n- `bcard`: the Bit2Me Card.\n- On the `origin` of a deposit, the payment method used: `card`, `bank-transfer`,\n  `google-pay`, `apple-pay`, `paypal`, `hub-latam`, `cvu`, `bizum`, `mbway`, `tikebit`,\n  `manual`, `b2m-card`, `promo-referral` or `profit-share`.\n\nNew values may appear with new products, so treat an unknown value as an opaque string.\n","enum":["pocket","trading","earn","blockchain","b2m","alias","email","phone","bankAccount","launchpad","vesting","bcard","card","bank-transfer","google-pay","apple-pay","paypal","hub-latam","cvu","bizum","mbway","tikebit","manual","b2m-card","promo-referral","profit-share"],"example":"pocket","type":"string"},"currency":{"description":"The asset moved on this side.","example":"EUR","type":"string"},"email":{"description":"Email the receiver was addressed by, on the `destination` of a payment sent with `class` `email`.","example":"jane.doe@example.com","nullable":true,"type":"string"},"fullName":{"description":"Name of the sender, on the `origin` of a payment the user received by email, phone or\nalias, and on some deposits when it is known. Omitted otherwise.\n","example":"Jane Doe","nullable":true,"type":"string"},"phone":{"allOf":[{"description":"Phone number split into country calling code and national number.","properties":{"countryCode":{"description":"Country calling code, without the leading `+`.","example":34,"maximum":999,"minimum":1,"type":"integer"},"number":{"description":"National number, without the country calling code.","example":600000000,"format":"int64","minimum":0,"type":"integer"}},"type":"object"}],"description":"Phone the receiver was addressed by, on the `destination` of a payment sent with `class` `phone`."},"pocketId":{"description":"Identifier of the pocket at this side. `null` when this side is not one of the user's pockets.","example":"9ca6cf96-4645-4658-b086-6cdb367c16bd","format":"uuid","nullable":true,"type":"string"},"pocketName":{"description":"Name of the pocket at this side, as the user named it. `null` when this side is not one\nof the user's pockets, for instance the Pro trading account or a blockchain address.\n","example":"Euro pocket","nullable":true,"type":"string"},"queryParams":{"additionalProperties":{"type":"string"},"description":"Memo sent with a withdrawal to an address, as given in `queryParams` when the proforma\nwas created. Present only on `destination`, and only when one was given.\n","example":{"memoId":"123456"},"type":"object"},"rate":{"allOf":[{"description":"The exchange rate applied, expressed as how much of `pair.quote` one unit of `pair.base` was\nworth at the time.\n","properties":{"extraDecimals":{"description":"Extra decimal places `value` should be shifted by, as a decimal string. Almost always\n`'0'`; it is non-zero only for assets whose price needs more precision than `value`\nalone carries.\n","example":"0","type":"string"},"pair":{"description":"Which two assets the rate relates.","properties":{"base":{"type":"string"},"quote":{"type":"string"}},"required":["base","quote"],"type":"object"},"value":{"allOf":[{"maxLength":50,"minLength":1,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}],"description":"The rate, as a decimal string.","example":"55535.00000000"}},"required":["value","pair"],"type":"object"}],"description":"Value of one unit of `currency` in EUR at the time of the movement (`pair.base` is\n`currency`, `pair.quote` is `EUR`). Omitted when the movement has no rate.\n"},"userAmount":{"description":"`amount` converted to the `userCurrency` requested, valued at the date of the movement.\nOnly in `GET /v1/wallet/transaction/{id}` when `userCurrency` is sent.\n","properties":{"amount":{"description":"The converted amount, as a decimal string.","example":"99.00002310","type":"string"},"currency":{"description":"The `userCurrency` requested.","example":"EUR","type":"string"}},"required":["currency","amount"],"type":"object"}},"type":"object"}],"description":"Where the funds came from."},"status":{"description":"Where the transaction is in its lifecycle.\n\n`completed`, `canceled`, `rejected`, `expired`, `refunded` and `error` are final. Everything\nelse is still in progress and will change on its own, so a client that polls should stop only\non a final status. `pending_user_information` means the user has to provide some information\nbefore the movement can go on.\n\nNote the inconsistent spelling of `pending_user_information`: it is the single status written\nwith underscores instead of hyphens.\n","enum":["pending","processing","reviewing","pending-review","awaiting-antifraud-decision","pending_user_information","completed","canceled","rejected","expired","refunded","error"],"example":"completed","type":"string"},"subtype":{"description":"What the transaction was for. Together with `type` it identifies the operation: a `deposit`\nwith subtype `trading` is money coming back from the Pro account, while a `withdrawal` with\nsubtype `trading` is money going into it.\n\nThe list is long because it accumulates every product that has ever moved funds, and new\nvalues are added as products appear. Treat an unknown subtype as an opaque string rather than\nfailing on it.\n","enum":["affiliates","airdrop","automatic-funding","automatic-send","bcard","birthday2me","card-purchase","earn","external","funding","futures","inactive-fee","junior","launchpad","launchpad-purchase","loan","loan-rectification","manual-send","manual-transfer","migration","otc","otc-buy","otc-sell","otc-swap","promo","purchase","receive","rectification","redeem","refund","reimbursement","safeguard-interest","seizures","sell","social-pay","stocks","swap","trading","transfer","vesting"],"example":"purchase","type":"string"},"transaction":{"description":"On-chain details. Present only when the movement has a blockchain transaction or was\ncharged a network fee.\n","properties":{"confirmationCount":{"description":"Number of confirmations seen for the blockchain transaction.","example":3,"format":"int32","minimum":0,"type":"integer"},"confirmedAt":{"description":"When the blockchain transaction was confirmed (ISO 8601). `null` until then.","example":"2024-03-27T09:31:02.000Z","format":"date-time","nullable":true,"type":"string"}},"type":"object"},"type":{"description":"Type of the transaction","enum":["deposit","transfer","withdrawal"],"example":"transfer","type":"string"},"updatedAt":{"description":"When the transaction record last changed (ISO 8601). It also moves when only the user's\nnote is edited, so it is not a reliable signal that the transaction itself progressed.\n","example":"2024-03-28T13:06:19.411Z","format":"date-time","type":"string"}},"required":["id","date","type","subtype","method","concept","origin","destination","status"],"type":"object"},{"properties":{"benefit":{"description":"Benefit of the user's loyalty level applied to the transaction, when there was one.","properties":{"flip":{"description":"Part of the conversion fee covered by the benefit.","properties":{"amount":{"description":"Amount covered, as a decimal string.","example":"0.50000000","type":"string"},"currency":{"description":"Asset of `amount`.","example":"EUR","type":"string"}},"type":"object"},"percentage":{"description":"Percentage of the fee covered by the benefit.","example":50,"maximum":100,"minimum":0,"type":"number"},"teller":{"description":"Part of the payment fee covered by the benefit.","properties":{"amount":{"description":"Amount covered, as a decimal string.","example":"0.25000000","type":"string"},"currency":{"description":"Asset of `amount`.","example":"EUR","type":"string"}},"type":"object"},"tier":{"description":"Loyalty level that granted the benefit.","example":"gold","nullable":true,"type":"string"}},"type":"object"},"fee":{"description":"The fees charged by the transaction. Each kind is present only when it applies.","properties":{"flip":{"description":"Conversion fee, on transactions that convert one asset into another.","properties":{"amount":{"description":"Amount charged, as a decimal string.","example":"1.00000000","type":"string"},"currency":{"description":"Asset the fee was charged in.","example":"EUR","type":"string"},"percentage":{"description":"Rate of the fee, as a decimal string (`0.0100` is 1%).","example":"0.0100","type":"string"}},"type":"object"},"network":{"description":"Blockchain network fee, on withdrawals to an address.","properties":{"amount":{"description":"Amount charged, as a decimal string.","example":"0.00002000","type":"string"},"currency":{"description":"Asset the fee was charged in.","example":"BTC","type":"string"}},"type":"object"},"teller":{"description":"Fees of the payment, on transactions paid or paid out with an external payment method.","properties":{"feeCurrency":{"description":"Currency the payment fees were charged in.","example":"EUR","type":"string"},"fixedFee":{"description":"Fixed part of the payment fee, as a decimal string.","example":"0.50000000","type":"string"},"id":{"description":"Identifier of the payment order, the same as `orders.tellerId`.","example":"a1b2c3d4-e5f6-4890-abcd-ef1234567890","format":"uuid","type":"string"},"variableFee":{"description":"Part of the payment fee proportional to the amount, as a decimal string.","example":"1.00000000","type":"string"},"variableFeePercentage":{"description":"Rate of the variable part, as a decimal string (`0.0100` is 1%).","example":"0.0100","type":"string"}},"type":"object"}},"type":"object"},"flip":{"description":"Conversion applied by the transaction, on transactions that convert one asset into another.","properties":{"rate":{"allOf":[{"description":"How much of `pair.quote` one unit of `pair.base` is worth.","properties":{"extraDecimals":{"description":"Number of decimal places `value` carries beyond the usual precision of `pair.quote`, as\nan integer string. `'0'` except for assets whose price is too small for that precision.\n","example":"0","pattern":"^[0-9]+$","type":"string"},"pair":{"description":"Which two assets the rate relates.","properties":{"base":{"description":"Asset being valued.","example":"BTC","type":"string"},"quote":{"description":"Asset the value is expressed in.","example":"EUR","type":"string"}},"required":["base","quote"],"type":"object"},"value":{"description":"The rate, as a decimal string. It already includes the `extraDecimals` decimals.","example":"55535.00000000","type":"string"}},"required":["value","pair"],"type":"object"}],"description":"Conversion rate applied."}},"type":"object"},"note":{"description":"The user's own note on the transaction, set with `PUT /v1/wallet/transaction/{id}`. `null` or omitted when there is none.","example":"Monthly savings","maxLength":100,"nullable":true,"type":"string"},"substractFeeType":{"description":"How the fees were applied: `REA` when they were added to what the origin paid, `SEA`\nwhen they were taken from what the destination received.\n","enum":["REA","SEA"],"example":"REA","type":"string"},"transaction":{"description":"On-chain details, with the hash of the blockchain transaction when there is one.","properties":{"confirmationCount":{"description":"Number of confirmations seen for the blockchain transaction.","example":3,"minimum":0,"nullable":true,"type":"integer"},"confirmedAt":{"description":"When the blockchain transaction was confirmed (ISO 8601). `null` until then.","example":"2024-03-27T09:31:02.000Z","format":"date-time","nullable":true,"type":"string"},"hash":{"description":"Hash of the blockchain transaction. `null` until it is known.","example":"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b","nullable":true,"type":"string"}},"type":"object"},"userAmount":{"allOf":[{"description":"An amount valued in the `userCurrency` of the request.","properties":{"amount":{"description":"The converted amount, as a decimal string.","example":"100.00000000","type":"string"},"currency":{"description":"The `userCurrency` of the request.","example":"EUR","type":"string"}},"required":["currency","amount"],"type":"object"}],"description":"The `destination` amount valued in `userCurrency`, when it was sent."},"userRate":{"allOf":[{"description":"Value of one unit of the `userCurrency` requested, in EUR.","properties":{"pair":{"description":"The `userCurrency` as `base` and `EUR` as `quote`.","properties":{"base":{"description":"The `userCurrency` requested.","example":"USD","type":"string"},"quote":{"description":"Always `EUR`.","example":"EUR","type":"string"}},"required":["base","quote"],"type":"object"},"value":{"description":"The rate, as a decimal string.","example":"0.92180000","type":"string"}},"required":["value","pair"],"type":"object"}],"description":"Value of one unit of `userCurrency` in EUR today, when `userCurrency` was sent and is not `EUR`."}},"type":"object"}],"description":"A transaction with its details. Besides the fields of the lists it carries the fees, the\nrate of the conversion, the user's note and, when `userCurrency` is sent, the amounts\nvalued in that currency.\n"}}},"description":"The transaction."},"400":{"content":{"application/json":{"examples":{"invalidCurrency":{"summary":"Unknown userCurrency","value":{"error":"Bad Request","message":"Invalid currency: XYZ","statusCode":400}},"invalidId":{"summary":"id that is not a UUID","value":{"error":"Bad Request","message":"Validation failed (uuid is expected)","statusCode":400}}},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The `id` is not a UUID (`Validation failed (uuid is expected)`), or `userCurrency` is not\na known currency (`Invalid currency: \u003cuserCurrency\u003e`).\n"},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"example":{"error":"Not Found","message":"transaction not found","statusCode":404},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"No transaction with this id has the user as sender or receiver."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get the details of one wallet transaction","tags":["Wallet"],"x-product":{"wallet":"Wallet"}},"put":{"description":"Sets the authenticated user's private note on one of their transactions. Sender and\nreceiver each have their own note, and each of them only sees their own, as `note` in\n`GET /v1/wallet/transaction/{id}`. Setting it again replaces the previous text.\n\nThe note cannot be cleared: an empty `note` changes nothing and is answered with `404`.\n","parameters":[{"description":"Identifier of the transaction, as returned by `GET /v3/wallet/transaction`.","in":"path","name":"id","required":true,"schema":{"example":"f040acdf-62b0-4040-9574-655fdcf7e541","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"note":"Monthly savings"},"schema":{"properties":{"note":{"allOf":[{"description":"Free text attached to a transaction, up to 100 characters.","example":"Monthly savings","maxLength":100,"type":"string"}],"description":"The note to store, up to 100 characters. It must not be empty.","example":"Monthly savings"}},"required":["note"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"result":true},"schema":{"properties":{"result":{"type":"boolean"}},"required":["result"],"type":"object"}}},"description":"The note was stored."},"400":{"content":{"application/json":{"example":{"errors":[{"code":"INVALID_REQUEST_PARAMETER","errors":[{"code":"MAX_LENGTH","message":"String is too long (101 chars), maximum 100","params":[101,100],"path":["note"]}],"in":"body","message":"Invalid parameter (data): Value failed JSON Schema validation","name":"data"}],"message":"Validation errors"},"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"The request does not match the contract: `note` is missing or longer than 100\ncharacters, or `id` is not a lowercase UUID.\n"},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"examples":{"emptyNote":{"summary":"Empty note","value":{"data":{},"error":"Not Found","message":"transaction not found","statusCode":404}},"notFound":{"summary":"Unknown transaction, or one of another user","value":{"data":{},"error":"Not Found","message":"Movement not found","statusCode":404}}},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The transaction does not exist or does not involve the user (`Movement not found`), or\n`note` was empty so nothing was stored (`transaction not found`).\n"}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Set the user's note on a transaction","tags":["Wallet"],"x-product":{"wallet":"Wallet"}}},"/v2/account/address":{"get":{"deprecated":true,"description":"**This endpoint is deprecated.** Use `GET /v3/account/address` instead, which returns\naddresses with sensitive data masked except for the country code.\n","parameters":[{"description":"Filter by a specific address UUID. When omitted, all addresses are returned.","in":"query","name":"addressId","schema":{"format":"uuid","type":"string"}},{"description":"Filter by residence flag.","in":"query","name":"isResidence","schema":{"type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"example":[{"city":"Madrid","countryCode":"ES","id":"550e8400-e29b-41d4-a716-446655440000","isDefaultAddress":true,"isResidence":true,"stateCode":"MD","streetAddress":"Calle Ejemplo 1","zip":"28001"}],"schema":{"items":{"properties":{"alias":{"maxLength":50,"type":"string"},"city":{"type":"string"},"countryCode":{"pattern":"^[A-Z]{2}$","type":"string"},"id":{"type":"string"},"isDefaultAddress":{"type":"boolean"},"isResidence":{"type":"boolean"},"stateCode":{"type":"string"},"streetAddress":{"type":"string"},"userId":{"type":"string"},"zip":{"type":"string"}},"required":["streetAddress","city","stateCode","zip","countryCode"],"type":"object"},"type":"array"}}},"description":"User addresses."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"User not found."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Deprecated, use GET /v3/account/address instead","tags":["Account Deprecated Methods"],"x-product":{"wallet":"Account"},"x-use":"GET /v3/account/address"},"post":{"description":"Adds a new address to the authenticated user. Requires `nationalityCountryCode` in\naddition to the standard address fields. Replaces `POST /v1/account/address`.\n","requestBody":{"content":{"application/json":{"example":{"city":"Madrid","countryCode":"ES","isResidence":true,"nationalityCountryCode":"ES","stateCode":"MD","streetAddress":"Calle Ejemplo 1","zip":"28001"},"schema":{"properties":{"alias":{"maxLength":50,"type":"string"},"city":{"type":"string"},"countryCode":{"pattern":"^[A-Z]{2}$","type":"string"},"id":{"type":"string"},"isDefaultAddress":{"type":"boolean"},"isResidence":{"type":"boolean"},"nationalityCountryCode":{"pattern":"^[A-Z]{2}$","type":"string"},"stateCode":{"type":"string"},"streetAddress":{"type":"string"},"zip":{"type":"string"}},"required":["streetAddress","city","stateCode","zip","countryCode","nationalityCountryCode"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"example":{"result":true},"schema":{"properties":{"result":{"type":"boolean"}},"required":["result"],"type":"object"}}},"description":"Address created."},"400":{"content":{"application/json":{"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"Incorrect address fields."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"User not found."},"406":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Residence already established or maximum number of addresses reached."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Create address","tags":["Account"],"x-product":{"wallet":"Account"}}},"/v2/blockchain-manager/travel-rule-order/{orderId}":{"post":{"description":"Submits the travel-rule information of a crypto order of the authenticated user: who the\ncounterparty is and what kind of wallet they use. For a deposit that is who sent the funds, and\nfor a withdrawal who receives them.\n\nCompared with `POST /v1/blockchain-manager/travel-rule-order/{orderId}`, the counterparty's address is\nreduced to its country (`address.countryCode`), identity documents, place of birth and date of\nbirth are not collected, and `ownershipVerified` can be sent for unhosted wallets.\n\nWhen `walletOwnership` is `other`, `personType`, `name` and `address` are required, and `surname`\ntoo unless `personType` is `company`.\n","parameters":[{"description":"ID of the crypto order (deposit or withdrawal) the information refers to.","example":"550e8400-e29b-41d4-a716-446655440030","in":"path","name":"orderId","required":true,"schema":{"format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"exchange-other":{"summary":"Deposit sent from an exchange account of someone else","value":{"address":{"countryCode":"ES"},"exchangeName":"Binance","name":"John","personType":"person","surname":"Doe","walletOwnership":"other","walletType":"exchange"}},"unhosted-own":{"summary":"Deposit sent from the user's own unhosted wallet","value":{"ownershipVerified":true,"walletOwnership":"own","walletType":"unhosted"}}},"schema":{"description":"Information about the counterparty of the order and their wallet: who sent the funds of a deposit, or who receives the funds of a withdrawal.\n\nWhen `walletOwnership` is `other`, `personType`, `name` and `address` are required, and `surname`\ntoo unless `personType` is `company`.\n","properties":{"address":{"description":"Address of the counterparty, reduced to its country. Required when `walletOwnership` is `other`.","properties":{"countryCode":{"description":"Country, as an ISO 3166-1 alpha-2 code.","example":"ES","pattern":"^[A-Z]{2}$","type":"string"}},"required":["countryCode"],"type":"object"},"exchangeName":{"description":"Name of the exchange of the counterparty wallet. Required when `walletType` is `exchange`.","example":"Binance","type":"string"},"name":{"description":"First name of the counterparty, or the company name. Required when `walletOwnership` is `other`.","example":"John","type":"string"},"ownershipVerified":{"description":"The user's statement that they control the counterparty wallet (proof of ownership).\nOnly taken into account when `walletType` is `unhosted`.\n","example":true,"type":"boolean"},"personType":{"description":"Whether the counterparty is a natural person or a company. Required when `walletOwnership` is `other`.","enum":["person","company"],"example":"person","type":"string"},"surname":{"description":"Last name of the counterparty. Required when `walletOwnership` is `other`, unless `personType` is `company`.","example":"Doe","type":"string"},"walletOwnership":{"description":"Whether the counterparty wallet belongs to the user (`own`) or to someone else (`other`).","enum":["own","other"],"example":"other","type":"string"},"walletType":{"description":"Whether the counterparty wallet is a hosted exchange wallet or an unhosted (self-custody) wallet.","enum":["exchange","unhosted"],"example":"exchange","type":"string"}},"required":["walletType","walletOwnership"],"type":"object"}}},"required":true},"responses":{"201":{"description":"Travel-rule information accepted. The response has no body."},"400":{"content":{"application/json":{"examples":{"missing-address":{"summary":"Someone else's wallet without `address`","value":{"error":"Bad Request","message":"should include more data for other ownership","statusCode":400}},"missing-name":{"summary":"Someone else's wallet without `name`","value":{"error":"Bad Request","message":"parameter name required when walletOwnership is other","statusCode":400}},"validation":{"summary":"Invalid value for `walletType`","value":{"error":"Bad Request","message":["walletType must be one of the following values: exchange, unhosted"],"statusCode":400}}},"schema":{"oneOf":[{"description":"Returned with `400` when the request is rejected field by field rather than against the\npublished contract. It is not the same shape as the contract validation error, and the\ndifference that catches integrators out is that **`message` is an array of strings here**,\nwhile everywhere else it is a single string.\n","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Bad Request","type":"string"},"message":{"description":"One human-readable sentence per failed constraint.","example":["iban should not be empty","iban must be a string"],"items":{"type":"string"},"type":"array"},"statusCode":{"description":"Repeats the HTTP status code.","example":400,"type":"integer"}},"required":["message","error","statusCode"],"type":"object"},{"description":"Business error returned by the operation.","properties":{"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"Human-readable description of the problem. Do not parse it; branch on the status.","example":"Address book 550e8400-e29b-41d4-a716-446655440000 not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"type":"integer"}},"required":["statusCode","message"],"type":"object"}]}}},"description":"The body is malformed (`FieldValidationErrorResponse`, with `message` as an array), or\nrequired information is missing for the given `walletType` or `walletOwnership`\n(`BlockchainManagerErrorResponse`, with `message` as a string).\n"},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"example":{"date":"2026-06-01T10:30:00.000Z","errorCode":"B2M_BLOCKCHAIN_MANAGER_TRAVEL_RULE_ORDER_NOT_FOUND","errorType":"GENERIC","message":"Travel rule order not found: 550e8400-e29b-41d4-a716-446655440030"},"schema":{"properties":{"date":{"description":"When the error was produced (ISO 8601)","example":"2025-11-11T11:11:11.111Z","format":"date-time","type":"string"},"errorCode":{"description":"Stable, machine-readable error identifier. Branch on this, never on `message`.","example":"B2M_BLOCKCHAIN_MANAGER_TRAVEL_RULE_ORDER_NOT_FOUND","type":"string"},"errorType":{"enum":["GENERIC"],"type":"string"},"message":{"description":"Human-readable description of the error, intended for logs rather than end users.","example":"Travel rule order not found: 00000000-0000-4000-8000-000000000000","type":"string"},"requestId":{"description":"Identifier of the request that failed. Quote it when reporting an incident.","example":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd","format":"uuid","type":"string"}},"required":["errorCode","message","errorType","date"],"type":"object"}}},"description":"No order with this ID exists for the authenticated user."},"409":{"content":{"application/json":{"example":{"date":"2026-06-01T10:30:00.000Z","errorCode":"B2M_BLOCKCHAIN_MANAGER_INVALID_TRAVEL_RULE_ORDER","errorType":"GENERIC","message":"Invalid Order 550e8400-e29b-41d4-a716-446655440030"},"schema":{"properties":{"date":{"description":"When the error was produced (ISO 8601)","example":"2025-11-11T11:11:11.111Z","format":"date-time","type":"string"},"errorCode":{"description":"Stable, machine-readable error identifier. Branch on this, never on `message`.","example":"B2M_BLOCKCHAIN_MANAGER_TRAVEL_RULE_ORDER_NOT_FOUND","type":"string"},"errorType":{"enum":["GENERIC"],"type":"string"},"message":{"description":"Human-readable description of the error, intended for logs rather than end users.","example":"Travel rule order not found: 00000000-0000-4000-8000-000000000000","type":"string"},"requestId":{"description":"Identifier of the request that failed. Quote it when reporting an incident.","example":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd","format":"uuid","type":"string"}},"required":["errorCode","message","errorType","date"],"type":"object"}}},"description":"The order does not accept travel-rule information in its current state."},"422":{"content":{"application/json":{"example":{"date":"2026-06-01T10:30:00.000Z","errorCode":"B2M_BLOCKCHAIN_MANAGER_UNPROCESSABLE_TRAVEL_RULE_ORDER","errorType":"GENERIC","message":"Unprocessable Travel Rule Order 550e8400-e29b-41d4-a716-446655440030"},"schema":{"properties":{"date":{"description":"When the error was produced (ISO 8601)","example":"2025-11-11T11:11:11.111Z","format":"date-time","type":"string"},"errorCode":{"description":"Stable, machine-readable error identifier. Branch on this, never on `message`.","example":"B2M_BLOCKCHAIN_MANAGER_TRAVEL_RULE_ORDER_NOT_FOUND","type":"string"},"errorType":{"enum":["GENERIC"],"type":"string"},"message":{"description":"Human-readable description of the error, intended for logs rather than end users.","example":"Travel rule order not found: 00000000-0000-4000-8000-000000000000","type":"string"},"requestId":{"description":"Identifier of the request that failed. Quote it when reporting an incident.","example":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd","format":"uuid","type":"string"}},"required":["errorCode","message","errorType","date"],"type":"object"}}},"description":"The travel-rule information could not be registered for the order."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Complete travel rule order","tags":["Blockchain Manager"],"x-product":{"wallet":"Funding"}}},"/v2/currency/assets":{"get":{"description":"Returns metadata for every asset the platform knows, keyed by symbol.\n\nFiat and crypto assets share the same shape. Testnet variants (`testnet: true`) are\n**included by default**; pass `includeTestnet=false` to drop them. Delisted assets are\nalso returned and carry `removedAt`, so filter on it before offering an asset to users.\n\nThe `exchange` field is omitted unless `showExchange=true`.\n\nNo authentication is required.\n","parameters":[{"description":"Pass `false` to exclude testnet assets. When omitted, testnet assets are included. Any value other than `true` counts as `false`.\n","example":false,"in":"query","name":"includeTestnet","schema":{"type":"boolean"}},{"description":"Pass `true` to include the `exchange` field on each asset. Any other value, or omitting it, leaves the field out.\n","example":true,"in":"query","name":"showExchange","schema":{"type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"examples":{"mixed":{"summary":"A fiat, a mainnet and a testnet entry","value":{"BTC":{"assetType":"currency","enabled":true,"hasPaymentRequest":true,"hexColor":"#eca24d","image":"/crypto-icons/v8/svg/btc-circle-solid-default.svg","isERC20Token":false,"mainwebUri":"bitcoin","name":"Bitcoin","slug":"bitcoin","symbol":"BTC","uriScheme":"bitcoin"},"BTCTEST":{"assetType":"currency","enabled":false,"hexColor":"#898888","image":"/crypto-icons/v8/svg/btctest-circle-solid-default.svg","name":"Bitcoin (Testnet)","network":"BTCTEST","pairsWith":[],"slug":"bitcoin","symbol":"BTCTEST","testnet":true},"EUR":{"assetType":"fiat","enabled":false,"hexColor":"#074c9e","image":"/crypto-icons/v8/svg/eur-circle-solid-default.svg","name":"Euro","pairsWith":[],"slug":"euro","symbol":"EUR"}}}},"schema":{"additionalProperties":{"description":"Asset metadata as stored in the currency service configuration. Fiat and crypto assets share this shape; fields that only make sense for crypto (`addressRegex`, `network`, `queryParams`, `consensus`) may be absent or carry placeholder values on fiat entries.\n","properties":{"addressRegex":{"description":"Regular expression that a destination address for this asset must match. Ignore it on fiat entries, which can carry a crypto regex copied from configuration.\n","type":"string"},"assetType":{"description":"Asset category. Values seen in service data are `currency`, `crypto`, `platform` and `fiat`.\n","type":"string"},"consensus":{"description":"Blockchain consensus mechanism (kebab industry name).\n","enum":["proof-of-work","proof-of-stake","delegated-proof-of-stake","proof-of-access","proof-of-spacetime","proof-of-coverage","proof-of-transfer","proof-of-believability","ripple-protocol-consensus","federated-byzantine-agreement","hashgraph","open-representative-voting","directed-acyclic-graph"],"nullable":true,"type":"string"},"createdAt":{"description":"Listing date as `YYYY-MM-DD`.","type":"string"},"enabled":{"type":"boolean"},"exchange":{"description":"Exchange identifier associated with the asset, such as `bit2me` or `kraken`. Only returned when the request sets `showExchange=true`.\n","type":"string"},"exponent":{"description":"Only present on a small subset of assets.","type":"number"},"hasImage":{"type":"boolean"},"hasPaymentRequest":{"type":"boolean"},"hexColor":{"description":"Brand colour as a CSS hex value.","type":"string"},"highRisk":{"type":"boolean"},"image":{"description":"Relative icon path. The service always rewrites it to `/crypto-icons/v8/svg/\u003csymbol in lowercase\u003e-circle-solid-default.svg`.\n","type":"string"},"isERC20Token":{"type":"boolean"},"lite":{"type":"boolean"},"loanable":{"type":"boolean"},"mainwebUri":{"type":"string"},"name":{"description":"Display name.","type":"string"},"network":{"description":"Network label, such as `ETHEREUM (ERC20)`.","type":"string"},"pairsWith":{"description":"Symbols this asset is paired with.","items":{"type":"string"},"type":"array"},"queryParams":{"additionalProperties":{"properties":{"enabled":{"type":"boolean"}},"type":"object"},"description":"Extra address fields the asset supports, keyed by parameter name (for example `memoId` or `destinationTag`).\n","type":"object"},"removedAt":{"description":"Delisting date as `YYYY-MM-DD`. Delisted assets are still returned; check this field before offering the asset.\n","type":"string"},"slug":{"description":"Human-readable identifier. Testnet variants reuse the slug of their mainnet asset.","type":"string"},"symbol":{"description":"Asset symbol. This is the identifier used by every other endpoint.","type":"string"},"testnet":{"description":"`true` on testnet variants such as `BTCTEST`. Usually absent on mainnet assets.\n","type":"boolean"},"ticker":{"type":"boolean"},"transactionUnitPriceScale":{"description":"Only present on a small subset of assets.","type":"number"},"unitPriceScale":{"description":"Only present on a small subset of assets.","type":"number"},"uriScheme":{"type":"string"}},"type":"object"},"type":"object"}}},"description":"Asset metadata keyed by symbol."},"500":{"content":{"application/json":{"examples":{"internal":{"value":{"message":"Internal server error","statusCode":500}}},"schema":{"description":"Error body produced by the currency service. `message` is a single string for business errors and an array of strings when the query fails validation. `error` is absent on a bare `404` and on unexpected `500` errors.\n","properties":{"error":{"description":"HTTP reason phrase, such as `Bad Request` or `Not Found`.","type":"string"},"message":{"description":"Error message, or one message per failed validation rule.","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"description":"HTTP status code, repeated in the body.","type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"Unexpected error in the currency service."}},"summary":"List all assets","tags":["Currency"],"x-product":{"wallet":"Market"}}},"/v2/currency/assets/{symbol}":{"get":{"description":"Returns metadata for a single asset. The shape matches one entry of\n`GET /v2/currency/assets`.\n\nThe lookup is an exact, case-sensitive match on the symbol: `BTC` works, `btc` returns\n`404`. Testnet and delisted assets are returned like any other; check `testnet` and\n`removedAt`.\n\nThe `exchange` field is omitted unless `showExchange=true`.\n\nNo authentication is required.\n","parameters":[{"description":"Asset symbol in uppercase, such as `BTC`, `EUR` or `BTCTEST`.","example":"BTC","in":"path","name":"symbol","required":true,"schema":{"type":"string"}},{"description":"Pass `true` to include the `exchange` field. Any other value, or omitting it, leaves the field out.\n","example":true,"in":"query","name":"showExchange","schema":{"type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"examples":{"b2mWithExchange":{"summary":"`B2M` with `showExchange=true`","value":{"addressRegex":"^(?:0x)?[0-9a-fA-F]{40}$","assetType":"currency","createdAt":"2021-11-01","enabled":true,"exchange":"bit2me","hasImage":true,"hasPaymentRequest":false,"hexColor":"#176dff","image":"/crypto-icons/v8/svg/b2m-circle-solid-default.svg","isERC20Token":true,"lite":false,"loanable":false,"mainwebUri":"bit2me-token","name":"Bit2Me Token","network":"ETHEREUM (ERC20)","pairsWith":["EUR"],"slug":"bit2me-token","symbol":"B2M","ticker":true,"uriScheme":"b2m"}},"bitcoin":{"summary":"`BTC` without `showExchange`","value":{"addressRegex":"^([13][a-km-zA-HJ-NP-Z1-9]{25,34})|^(bc1([qpzry9x8gf2tvdw0s3jn54khce6mua7l]{39}|[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{59}))$","assetType":"currency","hasImage":true,"hasPaymentRequest":true,"hexColor":"#eca24d","image":"/crypto-icons/v8/svg/btc-circle-solid-default.svg","isERC20Token":false,"mainwebUri":"bitcoin","name":"Bitcoin","slug":"bitcoin","symbol":"BTC","uriScheme":"bitcoin"}}},"schema":{"description":"Asset metadata as stored in the currency service configuration. Fiat and crypto assets share this shape; fields that only make sense for crypto (`addressRegex`, `network`, `queryParams`, `consensus`) may be absent or carry placeholder values on fiat entries.\n","properties":{"addressRegex":{"description":"Regular expression that a destination address for this asset must match. Ignore it on fiat entries, which can carry a crypto regex copied from configuration.\n","type":"string"},"assetType":{"description":"Asset category. Values seen in service data are `currency`, `crypto`, `platform` and `fiat`.\n","type":"string"},"consensus":{"description":"Blockchain consensus mechanism (kebab industry name).\n","enum":["proof-of-work","proof-of-stake","delegated-proof-of-stake","proof-of-access","proof-of-spacetime","proof-of-coverage","proof-of-transfer","proof-of-believability","ripple-protocol-consensus","federated-byzantine-agreement","hashgraph","open-representative-voting","directed-acyclic-graph"],"nullable":true,"type":"string"},"createdAt":{"description":"Listing date as `YYYY-MM-DD`.","type":"string"},"enabled":{"type":"boolean"},"exchange":{"description":"Exchange identifier associated with the asset, such as `bit2me` or `kraken`. Only returned when the request sets `showExchange=true`.\n","type":"string"},"exponent":{"description":"Only present on a small subset of assets.","type":"number"},"hasImage":{"type":"boolean"},"hasPaymentRequest":{"type":"boolean"},"hexColor":{"description":"Brand colour as a CSS hex value.","type":"string"},"highRisk":{"type":"boolean"},"image":{"description":"Relative icon path. The service always rewrites it to `/crypto-icons/v8/svg/\u003csymbol in lowercase\u003e-circle-solid-default.svg`.\n","type":"string"},"isERC20Token":{"type":"boolean"},"lite":{"type":"boolean"},"loanable":{"type":"boolean"},"mainwebUri":{"type":"string"},"name":{"description":"Display name.","type":"string"},"network":{"description":"Network label, such as `ETHEREUM (ERC20)`.","type":"string"},"pairsWith":{"description":"Symbols this asset is paired with.","items":{"type":"string"},"type":"array"},"queryParams":{"additionalProperties":{"properties":{"enabled":{"type":"boolean"}},"type":"object"},"description":"Extra address fields the asset supports, keyed by parameter name (for example `memoId` or `destinationTag`).\n","type":"object"},"removedAt":{"description":"Delisting date as `YYYY-MM-DD`. Delisted assets are still returned; check this field before offering the asset.\n","type":"string"},"slug":{"description":"Human-readable identifier. Testnet variants reuse the slug of their mainnet asset.","type":"string"},"symbol":{"description":"Asset symbol. This is the identifier used by every other endpoint.","type":"string"},"testnet":{"description":"`true` on testnet variants such as `BTCTEST`. Usually absent on mainnet assets.\n","type":"boolean"},"ticker":{"type":"boolean"},"transactionUnitPriceScale":{"description":"Only present on a small subset of assets.","type":"number"},"unitPriceScale":{"description":"Only present on a small subset of assets.","type":"number"},"uriScheme":{"type":"string"}},"type":"object"}}},"description":"Metadata for the requested asset."},"404":{"content":{"application/json":{"examples":{"notFound":{"value":{"error":"Not Found","message":"asset not found","statusCode":404}}},"schema":{"description":"Error body produced by the currency service. `message` is a single string for business errors and an array of strings when the query fails validation. `error` is absent on a bare `404` and on unexpected `500` errors.\n","properties":{"error":{"description":"HTTP reason phrase, such as `Bad Request` or `Not Found`.","type":"string"},"message":{"description":"Error message, or one message per failed validation rule.","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"description":"HTTP status code, repeated in the body.","type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"No asset has exactly this symbol."},"500":{"content":{"application/json":{"examples":{"internal":{"value":{"message":"Internal server error","statusCode":500}}},"schema":{"description":"Error body produced by the currency service. `message` is a single string for business errors and an array of strings when the query fails validation. `error` is absent on a bare `404` and on unexpected `500` errors.\n","properties":{"error":{"description":"HTTP reason phrase, such as `Bad Request` or `Not Found`.","type":"string"},"message":{"description":"Error message, or one message per failed validation rule.","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"description":"HTTP status code, repeated in the body.","type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"Unexpected error in the currency service."}},"summary":"Get asset metadata","tags":["Currency"],"x-product":{"wallet":"Market"}}},"/v2/earn/apy":{"get":{"description":"Returns the current annual percentage yields grouped by currency. Each currency key\nmaps to an object whose keys are reward periods (`daily`, `weekly`, `monthly`) and\nwhose values are the corresponding APY as a number.\n\nThis is a public catalog endpoint — no authentication required.\n","responses":{"200":{"content":{"application/json":{"example":{"BTC":{"daily":0.035,"monthly":0.045,"weekly":0.04},"ETH":{"daily":0.025,"monthly":0.035,"weekly":0.03}},"schema":{"additionalProperties":{"properties":{"daily":{"description":"Daily APY","type":"number"},"monthly":{"description":"Monthly APY","type":"number"},"weekly":{"description":"Weekly APY","type":"number"}},"type":"object"},"description":"Annual percentage yields by currency. Top-level keys are currency codes (e.g. BTC, ETH); each value is the APY by reward period.","type":"object"}}},"description":"APY rates by currency."},"500":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Internal server error."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"summary":"Get current APY rates by currency","tags":["Earn"],"x-product":{"wallet":"Earn"}}},"/v2/earn/assets":{"get":{"description":"Returns information about all supported earn currencies, including deposit/withdrawal\nstatus, allowed reward currencies, lock periods, APY boosts, tags, and category\nmembership.\n\nOptionally filter by pool type (`partner`, `farming-pool`).\n\nThis is a public catalog endpoint — no authentication required.\n","parameters":[{"description":"Filter by pool type.","in":"query","name":"type","schema":{"enum":["partner","farming-pool"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"properties":{"categoryIds":{"items":{"type":"string"},"type":"array"},"createdAt":{"format":"date-time","type":"string"},"currenciesRewardAllowed":{"description":"Currency rewards allowed with their info","items":{"properties":{"currency":{"description":"Currency where can receive rewards","type":"string"},"extraYield":{"description":"Extra Yield by currency applied in the reward","type":"number"},"extraYieldByRewardType":{"properties":{"daily":{"type":"number"},"monthly":{"type":"number"},"weekly":{"type":"number"}},"type":"object"},"type":{"description":"Reward type","enum":["daily","weekly","monthly"],"type":"string"}},"type":"object"},"type":"array"},"currency":{"description":"Currency symbol, it should be an allowed currency","type":"string"},"depositDisabled":{"description":"If set to true, deposits on that currency are not allowed.","type":"boolean"},"depositTermsAndConditions":{"description":"Terms and Conditions code to make deposit operations if needed","nullable":true,"type":"string"},"disabled":{"description":"Currency status on earn","type":"boolean"},"isNew":{"description":"Currency added on earn in the last 7 days","type":"boolean"},"levelExtraYieldPercentage":{"description":"Percentage of base APY applied to increment to APY by currency and user level","type":"number"},"levelExtraYieldType":{"enum":["space-pool","provided"],"type":"string"},"lockPeriodsAllowed":{"items":{"properties":{"lockPeriodId":{"type":"string"},"months":{"type":"integer"}},"required":["lockPeriodId","months"],"type":"object"},"type":"array"},"name":{"description":"Alternative name for Earn Currency","nullable":true,"type":"string"},"poolId":{"type":"string"},"symbolImageUrl":{"description":"URL of alternative image symbol","nullable":true,"type":"string"},"tags":{"items":{"properties":{"createdAt":{"format":"date-time","type":"string"},"icon":{"enum":["flame"],"nullable":true,"type":"string"},"order":{"type":"number"},"poolId":{"type":"string"},"poolTagId":{"type":"string"},"translatedTexts":{"items":{"properties":{"language":{"type":"string"},"translation":{"type":"string"}},"required":["language","translation"],"type":"object"},"type":"array"},"type":{"enum":["normal","highlight"],"type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["poolTagId","poolId","type","order","translatedTexts","createdAt","updatedAt"],"type":"object"},"type":"array"},"withdrawalDisabled":{"description":"If set to true, withdrawals on that currency are not allowed.","type":"boolean"}},"required":["poolId","currency","name","disabled","depositDisabled","withdrawalDisabled","isNew","currenciesRewardAllowed","lockPeriodsAllowed","levelExtraYieldPercentage","levelExtraYieldType","symbolImageUrl","tags","createdAt","categoryIds"],"type":"object"},"type":"array"}}},"description":"List of supported earn currencies."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"summary":"Get supported earn currencies","tags":["Earn"],"x-product":{"wallet":"Earn"}}},"/v2/earn/wallets":{"get":{"description":"Returns the authenticated user's earn wallets, each showing the currency, balance, and\noptional lock period. Supports sorting by currency or balance, and pagination via\n`offset` / `limit`.\n","parameters":[{"description":"Fiat currency code for converted balance values (e.g. `EUR`).","in":"query","name":"userCurrency","schema":{"type":"string"}},{"description":"Field to sort by.","in":"query","name":"sortBy","schema":{"enum":["currency","balance"],"type":"string"}},{"description":"Sort direction.","in":"query","name":"sortDirection","schema":{"enum":["ascending","descending"],"type":"string"}},{"description":"Number of records to skip.","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"Maximum number of records to return.","in":"query","name":"limit","schema":{"default":20,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"example":{"data":[{"balance":"0.15432100","convertedBalance":{"currency":"EUR","value":"4500.00"},"createdAt":"2025-01-15T10:00:00Z","currency":"BTC","updatedAt":"2026-09-20T14:30:00Z","userId":"550e8400-e29b-41d4-a716-446655440000","walletId":"550e8400-e29b-41d4-a716-446655440001"},{"balance":"2.50000000","convertedBalance":{"currency":"EUR","value":"6200.00"},"createdAt":"2025-03-01T08:00:00Z","currency":"ETH","updatedAt":"2026-09-20T14:30:00Z","userId":"550e8400-e29b-41d4-a716-446655440000","walletId":"550e8400-e29b-41d4-a716-446655440002"}],"total":2},"schema":{"properties":{"data":{"items":{"properties":{"balance":{"type":"string"},"convertedBalance":{"properties":{"currency":{"type":"string"},"value":{"type":"string"}},"type":"object"},"createdAt":{"format":"date-time","type":"string"},"currency":{"type":"string"},"lockPeriod":{"properties":{"lockPeriodId":{"type":"string"},"months":{"type":"integer"}},"required":["lockPeriodId","months"],"type":"object"},"updatedAt":{"format":"date-time","type":"string"},"userId":{"type":"string"},"walletId":{"type":"string"}},"required":["walletId","userId","currency","balance","convertedBalance","createdAt","updatedAt"],"type":"object"},"type":"array"},"total":{"type":"integer"}},"required":["total","data"],"type":"object"}}},"description":"Paginated list of earn wallets."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"List earn wallets","tags":["Earn"],"x-product":{"wallet":"Earn"}}},"/v2/loan/currency/configuration":{"get":{"description":"Lists the currencies that can be borrowed, with their APR, limits and available liquidity,\nand the currencies that can be pledged as guarantee, with their LTV settings. Disabled\ncurrencies are listed too; check `enabled` before offering them.\n\nThis is a public endpoint: it needs no authentication. `liquidity` and `liquidityStatus` may\ntake a few moments to reflect the latest loans.\n","responses":{"200":{"content":{"application/json":{"example":{"guaranteeCurrencies":[{"createdAt":"2024-07-16T15:49:30.646Z","currency":"BTC","currencyConfigurationGuaranteeId":"8f4a2d17-c6b3-4e90-9a5d-1e7c3b8f2a64","enabled":true,"initialLtv":"0.5000","liquidationLtv":"0.8500","updatedAt":"2026-09-30T08:02:11.517Z"}],"loanCurrencies":[{"apr":"0.1500","createdAt":"2024-07-16T15:49:30.646Z","currency":"USDC","currencyConfigurationLoanId":"2b9e6c41-7d3a-4f85-a0c2-58e1d4f7b936","enabled":true,"liquidity":"25800.000000000000000000","liquidityStatus":"high","maximumAmount":"25800.000000000000000000","minimumAmount":"50.000000000000000000","updatedAt":"2026-09-30T08:02:11.517Z"}]},"schema":{"description":"Currencies that can be borrowed and currencies that can be pledged as guarantee.","properties":{"guaranteeCurrencies":{"description":"Currencies that can be pledged as guarantee.","items":{"description":"A currency that can be pledged as guarantee.","properties":{"createdAt":{"description":"When the configuration was created.","example":"2024-07-16T15:49:30.646Z","format":"date-time","type":"string"},"currency":{"description":"Symbol of the currency.","example":"BTC","type":"string"},"currencyConfigurationGuaranteeId":{"description":"Identifier of the configuration.","example":"8f4a2d17-c6b3-4e90-9a5d-1e7c3b8f2a64","format":"uuid","type":"string"},"enabled":{"description":"Whether new loans can be guaranteed with this currency. Disabled currencies are listed too.","example":true,"type":"boolean"},"initialLtv":{"description":"LTV configured for new loans guaranteed with this currency, as a fraction.","example":"0.5000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"liquidationLtv":{"description":"LTV configured as the liquidation threshold for loans guaranteed with this currency, as a fraction.","example":"0.8500","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"updatedAt":{"description":"When the configuration was last changed.","example":"2026-09-30T08:02:11.517Z","format":"date-time","type":"string"}},"required":["currencyConfigurationGuaranteeId","currency","enabled","liquidationLtv","initialLtv"],"type":"object"},"type":"array"},"loanCurrencies":{"description":"Currencies that can be borrowed.","items":{"description":"A currency that can be borrowed.","properties":{"apr":{"description":"Base APR of loans in this currency, as a fraction (`0.1500` is 15 %), before the user's\ndiscounts.\n","example":"0.1500","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"createdAt":{"description":"When the configuration was created.","example":"2024-07-16T15:49:30.646Z","format":"date-time","type":"string"},"currency":{"description":"Symbol of the currency.","example":"USDC","type":"string"},"currencyConfigurationLoanId":{"description":"Identifier of the configuration.","example":"2b9e6c41-7d3a-4f85-a0c2-58e1d4f7b936","format":"uuid","type":"string"},"enabled":{"description":"Whether new loans can be requested in this currency. Disabled currencies are listed too.","example":true,"type":"boolean"},"liquidity":{"description":"Amount Bit2Me can lend right now in this currency, capped at `maximumAmount`. Requesting a\nlarger loan fails with `409`.\n","example":"25800.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"liquidityStatus":{"description":"How much can still be borrowed in this currency:\n\n- `high`: most of the lending capacity is available.\n- `medium`: part of the lending capacity is in use.\n- `low`: little lending capacity is left.\n- `not_available`: less than `minimumAmount` is left, so no loan can be requested.\n","enum":["high","medium","low","not_available"],"example":"high","type":"string"},"maximumAmount":{"description":"Largest loan amount, in this currency.","example":"25800.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"minimumAmount":{"description":"Smallest loan amount, in this currency.","example":"50.000000000000000000","pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"},"updatedAt":{"description":"When the configuration was last changed.","example":"2026-09-30T08:02:11.517Z","format":"date-time","type":"string"}},"required":["currencyConfigurationLoanId","currency","enabled","liquidity","liquidityStatus","apr","minimumAmount","maximumAmount"],"type":"object"},"type":"array"}},"required":["loanCurrencies","guaranteeCurrencies"],"type":"object"}}},"description":"The loan and guarantee currencies."}},"summary":"Get loan currency configuration","tags":["Loan"],"x-product":{"wallet":"Loan"}}},"/v2/trading/market-config":{"get":{"description":"Returns the markets available to the caller and the rules an order must respect in each\none: amount and price limits, minimum order value and decimal precision. Validate orders\nagainst these values before sending them to avoid `412` rejections.\n\nAuthentication is optional and changes the result: `restricted` markets are listed only for\nthe users granted access, `disabled` markets are never listed, and `enabled_at` markets are\nlisted once their opening date has passed.\n\nThe response is a plain array; when `limit` is not sent, every market is returned.\n","parameters":[{"description":"Only this market, as `BASE/QUOTE`. The response is still an array, empty when the market does not exist.","in":"query","name":"symbol","schema":{"description":"Market symbol as `BASE/QUOTE`, uppercase and separated by a slash (`BTC/EUR`). The hyphenated\nform (`BTC-EUR`) is not accepted: order creation answers `400 Symbol BTC-EUR is wrong` and the\nmarket data endpoints answer `404 Market not found for symbol BTC-EUR`. The list of valid\nsymbols is `GET /v2/trading/market-config`.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"}},{"description":"Only markets in this state. `disabled` markets are never listed, so that value returns an\nempty array.\n","in":"query","name":"marketEnabled","schema":{"description":"- `enabled`: open for trading.\n- `enabled_at`: opens at `marketEnabledAt`. It is listed only once that date has passed.\n- `frozen`: listed, but new orders and cancellations are rejected with `412`.\n- `restricted`: open only to the users granted access; it is listed only for them.\n- `disabled`: closed. It never appears in the listings.\n","enum":["enabled","enabled_at","frozen","restricted","disabled"],"example":"enabled","type":"string"}},{"description":"Maximum number of markets to return. All of them when omitted.","in":"query","name":"limit","schema":{"example":50,"minimum":1,"type":"integer"}},{"description":"Number of markets to skip.","in":"query","name":"offset","schema":{"default":0,"example":0,"minimum":0,"type":"integer"}},{"description":"Field to sort by. Any other value is ignored.","in":"query","name":"sort","schema":{"default":"symbol","enum":["id","symbol","minAmount","maxAmount","minPrice","maxPrice","tickSize","minOrderSize","pricePrecision","amountPrecision"],"example":"symbol","type":"string"}},{"description":"Sort direction. Any other value is ignored.","in":"query","name":"direction","schema":{"enum":["asc","desc"],"example":"asc","type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"noMatch":{"summary":"No market matches the filters","value":[]},"openMarket":{"summary":"A market open for trading","value":[{"amountPrecision":6,"feeMakerPercentage":0,"feeTakerPercentage":0,"id":"767a9906-3757-4d9c-8d90-504eb0a35a18","initialPrice":0,"marketEnabled":"enabled","marketEnabledAt":null,"maxAmount":20,"maxPrice":1000000,"minAmount":0.0001,"minOrderSize":1,"minPrice":1000,"pricePrecision":4,"symbol":"BTC/EUR","tickSize":0.000001}]},"scheduledMarket":{"summary":"A market that opened on a scheduled date","value":[{"amountPrecision":2,"feeMakerPercentage":0,"feeTakerPercentage":0,"id":"0c5d8e2a-4b7f-4e91-a3d6-9f2b1c7e5a40","initialPrice":0.005,"marketEnabled":"enabled_at","marketEnabledAt":"2024-06-03T10:00:00.000Z","maxAmount":1000000,"maxPrice":100,"minAmount":1,"minOrderSize":1,"minPrice":0.0001,"pricePrecision":6,"symbol":"B2M/EUR","tickSize":0.000001}]}},"schema":{"items":{"description":"Trading rules of one market. Orders that break them are rejected with `412`.","properties":{"amountPrecision":{"description":"Maximum decimal places accepted in `amount`.","example":6,"minimum":0,"type":"integer"},"feeMakerPercentage":{"description":"Currently always `0`: it does not reflect the fee charged. The fee actually applied is on\neach trade (`feePercentage`).\n","example":0,"nullable":true,"type":"number"},"feeTakerPercentage":{"description":"Currently always `0`: it does not reflect the fee charged. The fee actually applied is on\neach trade (`feePercentage`).\n","example":0,"nullable":true,"type":"number"},"id":{"description":"Market identifier.","example":"767a9906-3757-4d9c-8d90-504eb0a35a18","format":"uuid","type":"string"},"initialPrice":{"description":"Reference price of a market that has not opened yet: until `marketEnabledAt`, buy orders\nmust be priced at or below it and sell orders at or above it. `0` when not applicable.\n","example":0,"minimum":0,"type":"number"},"marketEnabled":{"description":"- `enabled`: open for trading.\n- `enabled_at`: opens at `marketEnabledAt`. It is listed only once that date has passed.\n- `frozen`: listed, but new orders and cancellations are rejected with `412`.\n- `restricted`: open only to the users granted access; it is listed only for them.\n- `disabled`: closed. It never appears in the listings.\n","enum":["enabled","enabled_at","frozen","restricted","disabled"],"example":"enabled","type":"string"},"marketEnabledAt":{"description":"Opening date of an `enabled_at` market; `null` for every other state.","example":"2024-06-03T10:00:00.000Z","format":"date-time","nullable":true,"type":"string"},"maxAmount":{"description":"Maximum order amount, in the base currency.","example":20,"minimum":0,"type":"number"},"maxPrice":{"description":"Maximum order price, in the quote currency.","example":1000000,"minimum":0,"type":"number"},"minAmount":{"description":"Minimum order amount, in the base currency.","example":0.0001,"minimum":0,"type":"number"},"minOrderSize":{"description":"Minimum order value (`amount * price`), in the quote currency.","example":1,"minimum":0,"type":"number"},"minPrice":{"description":"Minimum order price, in the quote currency.","example":1000,"minimum":0,"type":"number"},"pricePrecision":{"description":"Maximum decimal places accepted in `price` and `stopPrice`.","example":4,"minimum":0,"type":"integer"},"symbol":{"description":"Market symbol as `BASE/QUOTE`, uppercase and separated by a slash (`BTC/EUR`). The hyphenated\nform (`BTC-EUR`) is not accepted: order creation answers `400 Symbol BTC-EUR is wrong` and the\nmarket data endpoints answer `404 Market not found for symbol BTC-EUR`. The list of valid\nsymbols is `GET /v2/trading/market-config`.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"},"tickSize":{"deprecated":true,"description":"Smallest price increment as a decimal number. Deprecated; use `pricePrecision`.","example":0.000001,"minimum":0,"type":"number"}},"required":["id","symbol","minAmount","maxAmount","minPrice","maxPrice","minOrderSize","pricePrecision","amountPrecision","marketEnabled"],"type":"object"},"type":"array"}}},"description":"Markets and their rules; an empty array when none matches."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]},{"NoAuth":[]}],"summary":"List market configurations","tags":["Trading"],"x-product":{"spot":"MarketData"}}},"/v2/trading/order-book":{"get":{"description":"Returns a snapshot of the aggregated order book of a market: resting orders grouped by\nprice, up to 100 levels per side. No authentication is required.\n\nThe snapshot can be a few moments old: rely on `timestamp` to know when it was taken, and use\nthe trading websocket for a live book.\n","parameters":[{"description":"Market as `BASE/QUOTE`.","in":"query","name":"symbol","required":true,"schema":{"description":"Market symbol as `BASE/QUOTE`, uppercase and separated by a slash (`BTC/EUR`). The hyphenated\nform (`BTC-EUR`) is not accepted: order creation answers `400 Symbol BTC-EUR is wrong` and the\nmarket data endpoints answer `404 Market not found for symbol BTC-EUR`. The list of valid\nsymbols is `GET /v2/trading/market-config`.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"asks":[[63614.2,0.0049614],[63624.8,0.057]],"bids":[[63614.1,0.05],[63614,0.01511771]],"symbol":"BTC/EUR","timestamp":1715871588147},"schema":{"description":"Aggregated order book of one market, up to 100 price levels per side.","properties":{"asks":{"description":"Sell side, best (lowest) price first. Each level is read by position: `[0]` price in the\nquote currency, `[1]` amount in the base currency. Ignore any further element.\n","example":[[63614.2,0.0049614],[63624.8,0.057]],"items":{"items":{"minimum":0,"type":"number"},"minItems":2,"type":"array"},"maxItems":100,"type":"array"},"bids":{"description":"Buy side, best (highest) price first. Each level is read by position: `[0]` price in the\nquote currency, `[1]` amount in the base currency. Ignore any further element.\n","example":[[63614.1,0.05],[63614,0.01511771]],"items":{"items":{"minimum":0,"type":"number"},"minItems":2,"type":"array"},"maxItems":100,"type":"array"},"symbol":{"description":"Market symbol as `BASE/QUOTE`, uppercase and separated by a slash (`BTC/EUR`). The hyphenated\nform (`BTC-EUR`) is not accepted: order creation answers `400 Symbol BTC-EUR is wrong` and the\nmarket data endpoints answer `404 Market not found for symbol BTC-EUR`. The list of valid\nsymbols is `GET /v2/trading/market-config`.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"},"timestamp":{"description":"When this snapshot was taken, in Unix epoch milliseconds.","example":1715871588147,"format":"int64","type":"integer"}},"required":["symbol","timestamp","asks","bids"],"type":"object"}}},"description":"Order book of the market. Both sides are empty arrays when there are no resting orders."},"400":{"content":{"application/json":{"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"`symbol` was not sent."},"404":{"content":{"application/json":{"example":{"error":"Not Found","message":"Market not found for symbol BTC-EUR","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":404},"schema":{"description":"Business error from the trading service. `message` is human-readable and may change; when\n`errorPayload.code` is present, branch on it instead.\n","properties":{"error":{"description":"Standard reason phrase of the status (`Bad Request`, `Not Found`, `Precondition Failed`...).","example":"Precondition Failed","type":"string"},"errorPayload":{"additionalProperties":true,"description":"Machine-readable detail. Present only on order creation, order cancellation, order trades\nand trading wallet deposits and withdrawals: `null` there when the error has no detail\n(deposits and withdrawals omit it instead). `code` identifies the error; the other\nproperties depend on it (for example `minAmount` for `ORDER_AMOUNT_LOWER_MARKET_MIN`).\n","nullable":true,"properties":{"code":{"description":"Stable error code.","example":"ORDER_AMOUNT_LOWER_MARKET_MIN","type":"string"}},"type":"object"},"message":{"description":"What went wrong, in English.","example":"The order amount can not be lower than 0.0001","type":"string"},"reqId":{"description":"Request identifier. Quote it when reporting an incident.","example":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","type":"string"},"statusCode":{"description":"Same value as the HTTP status.","example":412,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"No market with this symbol exists."}},"summary":"Get the order book","tags":["Trading"],"x-product":{"spot":"MarketData"}}},"/v2/trading/tickers":{"get":{"description":"Returns 24-hour statistics (open, close, high, low, volumes, change) and the best bid and ask\nof every market, or only of `symbol` when it is sent. The response is always an array, with\na single entry when filtering by `symbol`.\n\nAuthentication is optional. Without it, markets reserved to specific users (`restricted`) are\nnot listed.\n","parameters":[{"description":"Only this market, as `BASE/QUOTE`.","in":"query","name":"symbol","schema":{"description":"Market symbol as `BASE/QUOTE`, uppercase and separated by a slash (`BTC/EUR`). The hyphenated\nform (`BTC-EUR`) is not accepted: order creation answers `400 Symbol BTC-EUR is wrong` and the\nmarket data endpoints answer `404 Market not found for symbol BTC-EUR`. The list of valid\nsymbols is `GET /v2/trading/market-config`.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":[{"ask":59459.4,"baseVolume":506.2471485105999,"bid":59459.3,"close":59459.3,"high":59807.8,"low":58259,"open":59692.2,"percentage":-0.39,"quoteVolume":30160053.557880376,"symbol":"BTC/EUR","timestamp":1715081606087}],"schema":{"items":{"description":"24-hour statistics of one market. A market without trades in the last 24 hours returns every\nnumeric field as `0`.\n","properties":{"ask":{"description":"Best sell price currently in the order book; `0` when there is no ask.","example":59459.4,"minimum":0,"type":"number"},"baseVolume":{"description":"Volume traded in the window, in the base currency.","example":506.2471485105999,"minimum":0,"type":"number"},"bid":{"description":"Best buy price currently in the order book; `0` when there is no bid.","example":59459.3,"minimum":0,"type":"number"},"close":{"description":"Last trade price.","example":59459.3,"minimum":0,"type":"number"},"high":{"description":"Highest trade price of the window.","example":59807.8,"minimum":0,"type":"number"},"low":{"description":"Lowest trade price of the window.","example":58259,"minimum":0,"type":"number"},"open":{"description":"First trade price of the 24-hour window.","example":59692.2,"minimum":0,"type":"number"},"percentage":{"description":"Change between `open` and `close`, as a percentage.","example":-0.39,"type":"number"},"quoteVolume":{"description":"Volume traded in the window, in the quote currency.","example":30160053.557880376,"minimum":0,"type":"number"},"symbol":{"description":"Market symbol as `BASE/QUOTE`, uppercase and separated by a slash (`BTC/EUR`). The hyphenated\nform (`BTC-EUR`) is not accepted: order creation answers `400 Symbol BTC-EUR is wrong` and the\nmarket data endpoints answer `404 Market not found for symbol BTC-EUR`. The list of valid\nsymbols is `GET /v2/trading/market-config`.\n","example":"BTC/EUR","pattern":"^[A-Z0-9]+/[A-Z0-9]+$","type":"string"},"timestamp":{"description":"When the statistics were computed, in Unix epoch milliseconds.","example":1715081606087,"format":"int64","type":"integer"}},"type":"object"},"type":"array"}}},"description":"Ticker statistics."},"404":{"content":{"application/json":{"example":{"error":"Not Found","message":"Market not found for symbol BTC-EUR","reqId":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","statusCode":404},"schema":{"description":"Business error from the trading service. `message` is human-readable and may change; when\n`errorPayload.code` is present, branch on it instead.\n","properties":{"error":{"description":"Standard reason phrase of the status (`Bad Request`, `Not Found`, `Precondition Failed`...).","example":"Precondition Failed","type":"string"},"errorPayload":{"additionalProperties":true,"description":"Machine-readable detail. Present only on order creation, order cancellation, order trades\nand trading wallet deposits and withdrawals: `null` there when the error has no detail\n(deposits and withdrawals omit it instead). `code` identifies the error; the other\nproperties depend on it (for example `minAmount` for `ORDER_AMOUNT_LOWER_MARKET_MIN`).\n","nullable":true,"properties":{"code":{"description":"Stable error code.","example":"ORDER_AMOUNT_LOWER_MARKET_MIN","type":"string"}},"type":"object"},"message":{"description":"What went wrong, in English.","example":"The order amount can not be lower than 0.0001","type":"string"},"reqId":{"description":"Request identifier. Quote it when reporting an incident.","example":"0b8f7c1e-5d2a-4c7e-9a51-2f3c8d6e4b10","type":"string"},"statusCode":{"description":"Same value as the HTTP status.","example":412,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"`symbol` was sent and no market with this symbol exists."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]},{"NoAuth":[]}],"summary":"Get ticker statistics","tags":["Trading"],"x-product":{"spot":"MarketData"}}},"/v2/wallet/pocket/{pocketId}/{network}/address":{"get":{"description":"Returns the addresses where the pocket can receive deposits on a blockchain network. When the\npocket has none on that network yet, one is created and returned. Deposits sent to a returned\naddress, with its `tag` when present, go to this pocket.\n\nRequires the complete identity verification level; below it the call answers `401`. The\nnetwork must support the pocket's asset.\n\nWhile the address of the pocket is being created, other calls answer `412`; retry after a\nmoment.\n","parameters":[{"description":"Pocket that will receive the deposits.","in":"path","name":"pocketId","required":true,"schema":{"description":"Pocket identifier, as returned by `GET /v1/wallet/pocket`.","example":"eb775a29-365d-4881-b7b9-1fa66fe1eb4d","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}},{"description":"Blockchain network id to deposit on, for instance `bitcoin`, `ethereum` or `xrpLedger`.","in":"path","name":"network","required":true,"schema":{"example":"bitcoin","minLength":1,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"bitcoin":{"summary":"Bitcoin address, no tag","value":[{"address":"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq","createdAt":"2024-02-19T10:12:44.318Z","id":"6b0f3d2a-9c4e-4a7b-8e1f-2d5c7a9b0e3f","network":"bitcoin","tag":null}]},"withTag":{"summary":"Address that needs a tag","value":[{"address":"rEb8TK3gBgk5auZkwc6sHnwrGVJH8DuaLh","createdAt":"2024-03-02T16:40:09.775Z","id":"1e7a4c9b-3d2f-4b8a-9e6c-5f0d2a8b7c4e","network":"xrpLedger","tag":"104366210"}]}},"schema":{"items":{"description":"A deposit address of a pocket on one network.","properties":{"address":{"allOf":[{"description":"Blockchain address.","example":"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq","maxLength":255,"minLength":1,"type":"string"}],"description":"Address to send the funds to."},"createdAt":{"description":"When the address was assigned to the pocket (ISO 8601).","example":"2024-02-19T10:12:44.318Z","format":"date-time","type":"string"},"id":{"description":"Identifier of the address record.","example":"6b0f3d2a-9c4e-4a7b-8e1f-2d5c7a9b0e3f","format":"uuid","type":"string"},"network":{"allOf":[{"description":"Blockchain network id, for instance `bitcoin`, `ethereum` or `xrpLedger`.","example":"bitcoin","type":"string"}],"description":"Network of the address, the one requested."},"tag":{"description":"Memo, tag or destination tag that must be sent with the deposit on networks that use one\n(for instance `xrpLedger`). `null` when the network does not use it.\n","nullable":true,"type":"string"}},"required":["id","createdAt","address","network","tag"],"type":"object"},"minItems":1,"type":"array"}}},"description":"The deposit addresses of the pocket on the network; at least one."},"400":{"content":{"application/json":{"examples":{"invalidPocketId":{"summary":"pocketId is not a lowercase UUID","value":{"errors":[{"code":"INVALID_REQUEST_PARAMETER","errors":[{"code":"PATTERN","message":"String does not match pattern ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$: EB775A29-365D-4881-B7B9-1FA66FE1EB4D","params":["^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","EB775A29-365D-4881-B7B9-1FA66FE1EB4D"],"path":[]}],"in":"path","message":"Invalid parameter (pocketId): Value failed JSON Schema validation","name":"pocketId"}],"message":"Validation errors"}},"unknownNetwork":{"summary":"The network does not exist","value":{"data":{},"error":"Bad Request","message":"network bitcoinn not found","statusCode":400}},"unsupportedNetwork":{"summary":"The network does not support the pocket's asset","value":{"data":{},"error":"Bad Request","message":"can not find addresses for currency BTC and network ethereum","statusCode":400}}},"schema":{"oneOf":[{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"},{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}]}}},"description":"The request cannot be served: `pocketId` is not a lowercase UUID\n(`RequestValidationErrorResponse`), the network does not exist\n(`network \u003cnetwork\u003e not found`), or the network does not support the pocket's asset\n(`can not find addresses for currency \u003casset\u003e and network \u003cnetwork\u003e`).\n"},"401":{"content":{"application/json":{"example":{"data":{},"error":"Unauthorized","message":"Low verification tier for userId: 2bf436fc-43e6-459a-b647-6b446f72ad96. Actual tier: 1. Minimum expected tier: 2","statusCode":401},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The user's identity verification level is below the complete level."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"example":{"data":{},"error":"Not Found","message":"pocket not found","statusCode":404},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The user has no pocket with this `pocketId`."},"412":{"content":{"application/json":{"example":{"data":{},"error":"Precondition Failed","message":"The pocket is in process of creating the address","statusCode":412},"schema":{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}}},"description":"The address of this pocket is still being created. Retry after a moment."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get the deposit addresses of a pocket, creating one if needed","tags":["Wallet"],"x-product":{"wallet":"Wallet"}}},"/v2/wallet/transaction":{"get":{"deprecated":true,"description":"Deprecated: use `GET /v3/wallet/transaction`, which pages with a cursor.\n\nReturns the movements of the authenticated user's wallet, newest first, paged with `offset`\nand `limit`, together with the `total` number of transactions that match the filters.\n\nAll filters are optional and combine with AND. Each item has the shape of\n`GET /v1/wallet/transaction/{id}` without the details: the fees, the user's note and the\namounts valued in another currency are only returned there.\n\nBuys, sells and swaps appear only once they are `completed`, and a transfer between two\ndifferent users appears as a `withdrawal` to the sender and as a `deposit` to the receiver.\n","parameters":[{"description":"Number of matching transactions to skip before the first one returned.","in":"query","name":"offset","schema":{"default":0,"example":0,"maximum":9007199254740991,"minimum":0,"type":"integer"}},{"description":"Maximum number of transactions in the page.","in":"query","name":"limit","schema":{"default":20,"example":20,"maximum":110,"minimum":1,"type":"integer"}},{"description":"Only transactions created during this calendar year. A year later than the current one\nis rejected with `400`.\n","in":"query","name":"year","schema":{"example":2024,"type":"integer"}},{"description":"Only transactions that move this asset, as origin or as destination.","in":"query","name":"currency","schema":{"example":"BTC","type":"string"}},{"description":"Only one kind of operation. Without it, every transaction of the user is listed.\n\n- `purchase`: buys, paid with an external payment method or from a pocket, and Launchpad\n  purchases.\n- `sell`: sells from a pocket.\n- `swap`: swaps between two pockets.\n- `deposit`: fiat deposits (card, Google Pay, bank transfer, Tikebit and manual ones),\n  referral rewards and profit sharing, and funds sent to Launchpad.\n- `withdrawal`: withdrawals to a bank account or card, manual withdrawals, and funds\n  returned from Launchpad.\n- `deposit-earn`: funds sent from the wallet to Earn.\n- `withdrawal-earn`: funds returned from Earn to the wallet.\n- `deposit-trading`: funds received in the wallet from the Pro trading account.\n- `withdrawal-trading`: funds sent from the wallet to the Pro trading account.\n- `send-pay`: Social Pay payments sent by email, phone or alias.\n- `receive-pay`: Social Pay payments received by email, phone or alias.\n- `purchase-bcard`: Bit2Me Card payments.\n- `reimburse-bcard`: Bit2Me Card refunds.\n- `send`: crypto sent to another user's Bit2Me address or to an external address.\n- `receive`: crypto received from another user's Bit2Me address or from the blockchain,\n  and vesting releases.\n","in":"query","name":"operation","schema":{"enum":["purchase","sell","swap","deposit","withdrawal","deposit-earn","withdrawal-earn","deposit-trading","withdrawal-trading","send-pay","receive-pay","purchase-bcard","reimburse-bcard","send","receive"],"example":"purchase","type":"string"}},{"description":"Only transactions linked to this payment order, the `orders.tellerId` of a transaction.","in":"query","name":"tellerId","schema":{"example":"a1b2c3d4-e5f6-4890-abcd-ef1234567890","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"empty":{"summary":"Nothing matches the filters","value":{"data":[],"total":0}},"page":{"summary":"A page with more results after it","value":{"data":[{"canceledAt":null,"completedAt":"2024-03-28T13:06:19.411Z","concept":"","date":"2024-03-28T13:06:18.032Z","denomination":{"amount":"100.00000000","currency":"EUR","rate":{"extraDecimals":"0","pair":{"base":"EUR","quote":"EUR"},"value":"1.00000000"}},"destination":{"address":null,"addressInBlacklist":null,"addressNetwork":null,"addressTag":null,"amount":"0.00178266","class":"pocket","currency":"BTC","pocketId":"eb775a29-365d-4881-b7b9-1fa66fe1eb4d","pocketName":"Bitcoin savings","rate":{"extraDecimals":"0","pair":{"base":"BTC","quote":"EUR"},"value":"55535.00000000"}},"frequency":"punctual","id":"f040acdf-62b0-4040-9574-655fdcf7e541","instantId":"2be1f76b-9332-4e96-9e58-8f9d65206b02","isInitialRecurringOrder":false,"method":"pocket","origin":{"amount":"100.00000000","class":"pocket","currency":"EUR","pocketId":"9ca6cf96-4645-4658-b086-6cdb367c16bd","pocketName":"Euro pocket","rate":{"extraDecimals":"0","pair":{"base":"EUR","quote":"EUR"},"value":"1.00000000"}},"status":"completed","subtype":"purchase","type":"transfer","updatedAt":"2024-03-28T13:06:19.411Z"},{"canceledAt":null,"completedAt":"2024-03-27T09:31:02.000Z","concept":"","date":"2024-03-27T09:12:44.120Z","denomination":{"amount":"0.01000000","currency":"BTC","rate":{"extraDecimals":"0","pair":{"base":"BTC","quote":"BTC"},"value":"1.00000000"}},"destination":{"address":"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq","addressInBlacklist":false,"addressNetwork":"bitcoin","addressTag":null,"amount":"0.01000000","class":"blockchain","currency":"BTC","pocketId":null,"pocketName":null},"frequency":"punctual","id":"3c1f9a7e-2b4d-4e8f-9a61-7d5e0c2b8f14","isInitialRecurringOrder":false,"method":"blockchain","origin":{"amount":"0.01002000","class":"pocket","currency":"BTC","pocketId":"eb775a29-365d-4881-b7b9-1fa66fe1eb4d","pocketName":"Bitcoin savings"},"status":"completed","subtype":"automatic-send","transaction":{"confirmationCount":3,"confirmedAt":"2024-03-27T09:31:02.000Z"},"type":"withdrawal","updatedAt":"2024-03-27T09:31:02.000Z"}],"total":15}}},"schema":{"properties":{"data":{"description":"The transactions of the page. Empty when nothing matches.","items":{"description":"A movement of funds in the user's wallet, seen from the user's side.\n\n`type`, `subtype` and `method` together say what the movement was, and `origin.class` and\n`destination.class` say what each side is, which in turn tells which of their fields are\nfilled. A transfer between two different users is shown as a `withdrawal` to the sender and\nas a `deposit` to the receiver.\n\nAmounts are decimal strings padded to the precision of their currency.\n","properties":{"canceledAt":{"description":"When the transaction was cancelled (ISO 8601). `null` unless it was cancelled.","format":"date-time","nullable":true,"type":"string"},"company":{"description":"Present only on bank withdrawals: the amount paid out to the bank account, in the\ncurrency of the Bit2Me entity that serves the user, with the rate used.\n","properties":{"destination":{"description":"Amount the bank account receives.","properties":{"amount":{"description":"Amount paid out, as a decimal string.","example":"41.00000000","type":"string"},"currency":{"description":"Currency the withdrawal is paid out in.","example":"EUR","type":"string"},"rate":{"allOf":[{"description":"The exchange rate applied, expressed as how much of `pair.quote` one unit of `pair.base` was\nworth at the time.\n","properties":{"extraDecimals":{"description":"Extra decimal places `value` should be shifted by, as a decimal string. Almost always\n`'0'`; it is non-zero only for assets whose price needs more precision than `value`\nalone carries.\n","example":"0","type":"string"},"pair":{"description":"Which two assets the rate relates.","properties":{"base":{"type":"string"},"quote":{"type":"string"}},"required":["base","quote"],"type":"object"},"value":{"allOf":[{"maxLength":50,"minLength":1,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}],"description":"The rate, as a decimal string.","example":"55535.00000000"}},"required":["value","pair"],"type":"object"}],"description":"Rate used to convert the withdrawn amount into `currency`."}},"required":["currency","amount","rate"],"type":"object"}},"type":"object"},"completedAt":{"description":"When the transaction was completed (ISO 8601). `null` until it is.","example":"2024-03-28T13:06:19.411Z","format":"date-time","nullable":true,"type":"string"},"concept":{"description":"Short description of the transaction, as set when it was created. An empty string when\nnone was set, which is frequent.\n","example":"","type":"string"},"date":{"description":"When the transaction was created (ISO 8601). Lists are sorted by it, newest first.","example":"2024-03-28T13:06:18.032Z","format":"date-time","type":"string"},"denomination":{"description":"The amount and currency the user expressed the operation in when creating it (the\n`amount` and `currency` of the proforma), with the rate of that currency at the time.\nOmitted on movements that do not have one.\n","properties":{"amount":{"description":"Amount the operation was requested for, as a decimal string.","example":"100.00000000","type":"string"},"currency":{"description":"Currency `amount` is expressed in.","example":"EUR","type":"string"},"rate":{"allOf":[{"description":"The exchange rate applied, expressed as how much of `pair.quote` one unit of `pair.base` was\nworth at the time.\n","properties":{"extraDecimals":{"description":"Extra decimal places `value` should be shifted by, as a decimal string. Almost always\n`'0'`; it is non-zero only for assets whose price needs more precision than `value`\nalone carries.\n","example":"0","type":"string"},"pair":{"description":"Which two assets the rate relates.","properties":{"base":{"type":"string"},"quote":{"type":"string"}},"required":["base","quote"],"type":"object"},"value":{"allOf":[{"maxLength":50,"minLength":1,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}],"description":"The rate, as a decimal string.","example":"55535.00000000"}},"required":["value","pair"],"type":"object"}],"description":"Rate between `currency` and the currency of the origin pocket when the operation was\ncreated. When both are the same it is `1`, with that currency on both sides of `pair`.\n"}},"type":"object"},"destination":{"allOf":[{"description":"One side of a transaction, either where the funds came from (`origin`) or where they went\n(`destination`).\n\nWhich properties are filled depends on `class`. The two sides do not carry the same keys:\n\n- Both sides always have `class`, `amount` and `currency`, and usually `pocketId` and\n  `pocketName`, which are `null` when the side is not one of the user's pockets.\n- Only `destination` carries `address`, `addressNetwork`, `addressTag` and\n  `addressInBlacklist`, present and `null` when they do not apply.\n- When the counterparty was addressed by email, phone or alias, its `pocketId` and\n  `pocketName` are omitted, and `email`, `phone`, `alias` or `fullName` take their place.\n- A Launchpad destination only carries `class`, `amount`, `currency` and `rate`.\n","properties":{"address":{"description":"Blockchain address of the movement, on `destination` only. `null` when the movement has no address.","example":"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq","nullable":true,"type":"string"},"addressInBlacklist":{"description":"Whether the address is flagged as high risk. `null` when there is no address or the check\ndoes not apply.\n","example":false,"nullable":true,"type":"boolean"},"addressNetwork":{"description":"Network id the address belongs to, for instance `bitcoin`. `null` when there is no\naddress.\n","example":"bitcoin","nullable":true,"type":"string"},"addressTag":{"description":"Destination tag or memo used with the address, on networks that route deposits with one.\n`null` when there is none.\n","nullable":true,"type":"string"},"alias":{"description":"Alias the receiver was addressed by, on the `destination` of a payment sent with `class` `alias`.","example":"janedoe","nullable":true,"type":"string"},"amount":{"description":"Amount moved on this side, as a decimal string. It differs between the two sides on any\ntransaction that converts or charges a fee, so read both rather than assuming they match.\n","example":"100.00000000","type":"string"},"bankAccount":{"description":"Bank account (usually an IBAN) at this side. Present on the `origin` of bank deposits and\non the `destination` of bank withdrawals; omitted otherwise.\n","example":"ES0000000000000000000000","nullable":true,"type":"string"},"class":{"description":"What kind of endpoint this side of the transaction is, which tells you which of the other\nfields are filled:\n\n- `pocket`: one of the user's own pockets, so `pocketId` and `pocketName` are set.\n- `trading`: the user's Pro trading account. It has no pocket, so `pocketId` and\n  `pocketName` are `null`.\n- `earn`: Earn, in the same way as `trading`.\n- `blockchain`: an on-chain send or receive; the address is on `destination`.\n- `b2m`: another Bit2Me user reached through one of its Bit2Me addresses. Its pocket\n  fields are `null`.\n- `email`, `phone`, `alias`: another user addressed by email, phone or alias.\n- `bankAccount`: a bank account, on the `destination` of a bank withdrawal.\n- `launchpad`, `vesting`: a Launchpad sale or a vesting release.\n- `bcard`: the Bit2Me Card.\n- On the `origin` of a deposit, the payment method used: `card`, `bank-transfer`,\n  `google-pay`, `apple-pay`, `paypal`, `hub-latam`, `cvu`, `bizum`, `mbway`, `tikebit`,\n  `manual`, `b2m-card`, `promo-referral` or `profit-share`.\n\nNew values may appear with new products, so treat an unknown value as an opaque string.\n","enum":["pocket","trading","earn","blockchain","b2m","alias","email","phone","bankAccount","launchpad","vesting","bcard","card","bank-transfer","google-pay","apple-pay","paypal","hub-latam","cvu","bizum","mbway","tikebit","manual","b2m-card","promo-referral","profit-share"],"example":"pocket","type":"string"},"currency":{"description":"The asset moved on this side.","example":"EUR","type":"string"},"email":{"description":"Email the receiver was addressed by, on the `destination` of a payment sent with `class` `email`.","example":"jane.doe@example.com","nullable":true,"type":"string"},"fullName":{"description":"Name of the sender, on the `origin` of a payment the user received by email, phone or\nalias, and on some deposits when it is known. Omitted otherwise.\n","example":"Jane Doe","nullable":true,"type":"string"},"phone":{"allOf":[{"description":"Phone number split into country calling code and national number.","properties":{"countryCode":{"description":"Country calling code, without the leading `+`.","example":34,"maximum":999,"minimum":1,"type":"integer"},"number":{"description":"National number, without the country calling code.","example":600000000,"format":"int64","minimum":0,"type":"integer"}},"type":"object"}],"description":"Phone the receiver was addressed by, on the `destination` of a payment sent with `class` `phone`."},"pocketId":{"description":"Identifier of the pocket at this side. `null` when this side is not one of the user's pockets.","example":"9ca6cf96-4645-4658-b086-6cdb367c16bd","format":"uuid","nullable":true,"type":"string"},"pocketName":{"description":"Name of the pocket at this side, as the user named it. `null` when this side is not one\nof the user's pockets, for instance the Pro trading account or a blockchain address.\n","example":"Euro pocket","nullable":true,"type":"string"},"queryParams":{"additionalProperties":{"type":"string"},"description":"Memo sent with a withdrawal to an address, as given in `queryParams` when the proforma\nwas created. Present only on `destination`, and only when one was given.\n","example":{"memoId":"123456"},"type":"object"},"rate":{"allOf":[{"description":"The exchange rate applied, expressed as how much of `pair.quote` one unit of `pair.base` was\nworth at the time.\n","properties":{"extraDecimals":{"description":"Extra decimal places `value` should be shifted by, as a decimal string. Almost always\n`'0'`; it is non-zero only for assets whose price needs more precision than `value`\nalone carries.\n","example":"0","type":"string"},"pair":{"description":"Which two assets the rate relates.","properties":{"base":{"type":"string"},"quote":{"type":"string"}},"required":["base","quote"],"type":"object"},"value":{"allOf":[{"maxLength":50,"minLength":1,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}],"description":"The rate, as a decimal string.","example":"55535.00000000"}},"required":["value","pair"],"type":"object"}],"description":"Value of one unit of `currency` in EUR at the time of the movement (`pair.base` is\n`currency`, `pair.quote` is `EUR`). Omitted when the movement has no rate.\n"},"userAmount":{"description":"`amount` converted to the `userCurrency` requested, valued at the date of the movement.\nOnly in `GET /v1/wallet/transaction/{id}` when `userCurrency` is sent.\n","properties":{"amount":{"description":"The converted amount, as a decimal string.","example":"99.00002310","type":"string"},"currency":{"description":"The `userCurrency` requested.","example":"EUR","type":"string"}},"required":["currency","amount"],"type":"object"}},"type":"object"}],"description":"Where the funds went."},"frequency":{"description":"How often the operation repeats. `punctual` is a one-off operation; the others belong to a\nrecurring order that runs every day, week or month. Movements with no frequency are reported\nas `punctual`.\n","enum":["punctual","daily","weekly","monthly"],"example":"punctual","type":"string"},"id":{"description":"Identifier of the transaction. Use it with `GET /v1/wallet/transaction/{id}`.","example":"f040acdf-62b0-4040-9574-655fdcf7e541","format":"uuid","type":"string"},"instantId":{"description":"Identifier of the conversion order behind the movement. Present only on movements that\nconverted one asset into another, such as buys, sells and swaps.\n","example":"2be1f76b-9332-4e96-9e58-8f9d65206b02","type":"string"},"isInitialRecurringOrder":{"description":"`true` when this movement is the first execution of a recurring order, the one run when\nthe order is created. `false` otherwise.\n","example":false,"type":"boolean"},"method":{"description":"How the funds moved. For an internal movement between the user's own pockets this is `pocket`;\nfor a blockchain send or receive it is `blockchain`; the rest identify the payment instrument\nor the way the counterparty was addressed.\n","enum":["alias","apple-pay","b2m-card","bank-transfer","bizum","blockchain","card","cvu","email","google-pay","hub-latam","launchpad","manual","mbway","paypal","phone","pocket","profit-share","promo-referral","redeem","redemption","tikebit"],"example":"pocket","type":"string"},"orders":{"allOf":[{"description":"Identifiers of the orders that produced the movement, to correlate it with an order created\nthrough another Bit2Me product. Each property is present only when that kind of order exists.\n","example":{"brokerageId":"f040acdf-62b0-4040-9574-655fdcf7e541","tellerId":"a1b2c3d4-e5f6-4890-abcd-ef1234567890"},"properties":{"blockchainManagerId":{"description":"Identifier of the blockchain order behind the movement, on some on-chain sends and receives.","example":"2be1f76b-9332-4e96-9e58-8f9d65206b02","format":"uuid","type":"string"},"brokerageId":{"description":"Identifier of the brokerage order behind the movement, such as an instant buy, sell or swap.","example":"f040acdf-62b0-4040-9574-655fdcf7e541","format":"uuid","type":"string"},"tellerId":{"description":"Identifier of the payment order behind the movement, such as a card purchase or a bank\nwithdrawal. It is the value accepted by the `tellerId` filter of the transaction lists.\n","example":"a1b2c3d4-e5f6-4890-abcd-ef1234567890","format":"uuid","type":"string"}},"type":"object"}],"description":"Identifiers of the orders that produced the movement. Omitted when there is none.\n"},"origin":{"allOf":[{"description":"One side of a transaction, either where the funds came from (`origin`) or where they went\n(`destination`).\n\nWhich properties are filled depends on `class`. The two sides do not carry the same keys:\n\n- Both sides always have `class`, `amount` and `currency`, and usually `pocketId` and\n  `pocketName`, which are `null` when the side is not one of the user's pockets.\n- Only `destination` carries `address`, `addressNetwork`, `addressTag` and\n  `addressInBlacklist`, present and `null` when they do not apply.\n- When the counterparty was addressed by email, phone or alias, its `pocketId` and\n  `pocketName` are omitted, and `email`, `phone`, `alias` or `fullName` take their place.\n- A Launchpad destination only carries `class`, `amount`, `currency` and `rate`.\n","properties":{"address":{"description":"Blockchain address of the movement, on `destination` only. `null` when the movement has no address.","example":"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq","nullable":true,"type":"string"},"addressInBlacklist":{"description":"Whether the address is flagged as high risk. `null` when there is no address or the check\ndoes not apply.\n","example":false,"nullable":true,"type":"boolean"},"addressNetwork":{"description":"Network id the address belongs to, for instance `bitcoin`. `null` when there is no\naddress.\n","example":"bitcoin","nullable":true,"type":"string"},"addressTag":{"description":"Destination tag or memo used with the address, on networks that route deposits with one.\n`null` when there is none.\n","nullable":true,"type":"string"},"alias":{"description":"Alias the receiver was addressed by, on the `destination` of a payment sent with `class` `alias`.","example":"janedoe","nullable":true,"type":"string"},"amount":{"description":"Amount moved on this side, as a decimal string. It differs between the two sides on any\ntransaction that converts or charges a fee, so read both rather than assuming they match.\n","example":"100.00000000","type":"string"},"bankAccount":{"description":"Bank account (usually an IBAN) at this side. Present on the `origin` of bank deposits and\non the `destination` of bank withdrawals; omitted otherwise.\n","example":"ES0000000000000000000000","nullable":true,"type":"string"},"class":{"description":"What kind of endpoint this side of the transaction is, which tells you which of the other\nfields are filled:\n\n- `pocket`: one of the user's own pockets, so `pocketId` and `pocketName` are set.\n- `trading`: the user's Pro trading account. It has no pocket, so `pocketId` and\n  `pocketName` are `null`.\n- `earn`: Earn, in the same way as `trading`.\n- `blockchain`: an on-chain send or receive; the address is on `destination`.\n- `b2m`: another Bit2Me user reached through one of its Bit2Me addresses. Its pocket\n  fields are `null`.\n- `email`, `phone`, `alias`: another user addressed by email, phone or alias.\n- `bankAccount`: a bank account, on the `destination` of a bank withdrawal.\n- `launchpad`, `vesting`: a Launchpad sale or a vesting release.\n- `bcard`: the Bit2Me Card.\n- On the `origin` of a deposit, the payment method used: `card`, `bank-transfer`,\n  `google-pay`, `apple-pay`, `paypal`, `hub-latam`, `cvu`, `bizum`, `mbway`, `tikebit`,\n  `manual`, `b2m-card`, `promo-referral` or `profit-share`.\n\nNew values may appear with new products, so treat an unknown value as an opaque string.\n","enum":["pocket","trading","earn","blockchain","b2m","alias","email","phone","bankAccount","launchpad","vesting","bcard","card","bank-transfer","google-pay","apple-pay","paypal","hub-latam","cvu","bizum","mbway","tikebit","manual","b2m-card","promo-referral","profit-share"],"example":"pocket","type":"string"},"currency":{"description":"The asset moved on this side.","example":"EUR","type":"string"},"email":{"description":"Email the receiver was addressed by, on the `destination` of a payment sent with `class` `email`.","example":"jane.doe@example.com","nullable":true,"type":"string"},"fullName":{"description":"Name of the sender, on the `origin` of a payment the user received by email, phone or\nalias, and on some deposits when it is known. Omitted otherwise.\n","example":"Jane Doe","nullable":true,"type":"string"},"phone":{"allOf":[{"description":"Phone number split into country calling code and national number.","properties":{"countryCode":{"description":"Country calling code, without the leading `+`.","example":34,"maximum":999,"minimum":1,"type":"integer"},"number":{"description":"National number, without the country calling code.","example":600000000,"format":"int64","minimum":0,"type":"integer"}},"type":"object"}],"description":"Phone the receiver was addressed by, on the `destination` of a payment sent with `class` `phone`."},"pocketId":{"description":"Identifier of the pocket at this side. `null` when this side is not one of the user's pockets.","example":"9ca6cf96-4645-4658-b086-6cdb367c16bd","format":"uuid","nullable":true,"type":"string"},"pocketName":{"description":"Name of the pocket at this side, as the user named it. `null` when this side is not one\nof the user's pockets, for instance the Pro trading account or a blockchain address.\n","example":"Euro pocket","nullable":true,"type":"string"},"queryParams":{"additionalProperties":{"type":"string"},"description":"Memo sent with a withdrawal to an address, as given in `queryParams` when the proforma\nwas created. Present only on `destination`, and only when one was given.\n","example":{"memoId":"123456"},"type":"object"},"rate":{"allOf":[{"description":"The exchange rate applied, expressed as how much of `pair.quote` one unit of `pair.base` was\nworth at the time.\n","properties":{"extraDecimals":{"description":"Extra decimal places `value` should be shifted by, as a decimal string. Almost always\n`'0'`; it is non-zero only for assets whose price needs more precision than `value`\nalone carries.\n","example":"0","type":"string"},"pair":{"description":"Which two assets the rate relates.","properties":{"base":{"type":"string"},"quote":{"type":"string"}},"required":["base","quote"],"type":"object"},"value":{"allOf":[{"maxLength":50,"minLength":1,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}],"description":"The rate, as a decimal string.","example":"55535.00000000"}},"required":["value","pair"],"type":"object"}],"description":"Value of one unit of `currency` in EUR at the time of the movement (`pair.base` is\n`currency`, `pair.quote` is `EUR`). Omitted when the movement has no rate.\n"},"userAmount":{"description":"`amount` converted to the `userCurrency` requested, valued at the date of the movement.\nOnly in `GET /v1/wallet/transaction/{id}` when `userCurrency` is sent.\n","properties":{"amount":{"description":"The converted amount, as a decimal string.","example":"99.00002310","type":"string"},"currency":{"description":"The `userCurrency` requested.","example":"EUR","type":"string"}},"required":["currency","amount"],"type":"object"}},"type":"object"}],"description":"Where the funds came from."},"status":{"description":"Where the transaction is in its lifecycle.\n\n`completed`, `canceled`, `rejected`, `expired`, `refunded` and `error` are final. Everything\nelse is still in progress and will change on its own, so a client that polls should stop only\non a final status. `pending_user_information` means the user has to provide some information\nbefore the movement can go on.\n\nNote the inconsistent spelling of `pending_user_information`: it is the single status written\nwith underscores instead of hyphens.\n","enum":["pending","processing","reviewing","pending-review","awaiting-antifraud-decision","pending_user_information","completed","canceled","rejected","expired","refunded","error"],"example":"completed","type":"string"},"subtype":{"description":"What the transaction was for. Together with `type` it identifies the operation: a `deposit`\nwith subtype `trading` is money coming back from the Pro account, while a `withdrawal` with\nsubtype `trading` is money going into it.\n\nThe list is long because it accumulates every product that has ever moved funds, and new\nvalues are added as products appear. Treat an unknown subtype as an opaque string rather than\nfailing on it.\n","enum":["affiliates","airdrop","automatic-funding","automatic-send","bcard","birthday2me","card-purchase","earn","external","funding","futures","inactive-fee","junior","launchpad","launchpad-purchase","loan","loan-rectification","manual-send","manual-transfer","migration","otc","otc-buy","otc-sell","otc-swap","promo","purchase","receive","rectification","redeem","refund","reimbursement","safeguard-interest","seizures","sell","social-pay","stocks","swap","trading","transfer","vesting"],"example":"purchase","type":"string"},"transaction":{"description":"On-chain details. Present only when the movement has a blockchain transaction or was\ncharged a network fee.\n","properties":{"confirmationCount":{"description":"Number of confirmations seen for the blockchain transaction.","example":3,"format":"int32","minimum":0,"type":"integer"},"confirmedAt":{"description":"When the blockchain transaction was confirmed (ISO 8601). `null` until then.","example":"2024-03-27T09:31:02.000Z","format":"date-time","nullable":true,"type":"string"}},"type":"object"},"type":{"description":"Type of the transaction","enum":["deposit","transfer","withdrawal"],"example":"transfer","type":"string"},"updatedAt":{"description":"When the transaction record last changed (ISO 8601). It also moves when only the user's\nnote is edited, so it is not a reliable signal that the transaction itself progressed.\n","example":"2024-03-28T13:06:19.411Z","format":"date-time","type":"string"}},"required":["id","date","type","subtype","method","concept","origin","destination","status"],"type":"object"},"type":"array"},"total":{"description":"Number of transactions that match the filters, across all pages.","example":15,"minimum":0,"type":"integer"}},"required":["data","total"],"type":"object"}}},"description":"One page of transactions, newest first, with the total that match."},"400":{"content":{"application/json":{"examples":{"invalidYear":{"summary":"year later than the current one","value":{"data":{},"error":"Bad Request","message":"invalid year","statusCode":400}},"limitOutOfRange":{"summary":"limit above 110","value":{"errors":[{"code":"INVALID_REQUEST_PARAMETER","errors":[{"code":"MAXIMUM","message":"Value 500 is greater than maximum 110","params":[500,110],"path":[]}],"in":"query","message":"Invalid parameter (limit): Value failed JSON Schema validation","name":"limit"}],"message":"Validation errors"}}},"schema":{"oneOf":[{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"},{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}]}}},"description":"The request was rejected. Two shapes are possible:\n\n- A parameter outside its declared constraints (`limit` out of range, an unknown\n  `operation`, a `tellerId` that is not a lowercase UUID, a `year` that is not an\n  integer) answers `RequestValidationErrorResponse`.\n- A `year` later than the current one answers `WalletErrorResponse` with\n  `invalid year`.\n"},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"List the user's wallet transactions (offset pagination)","tags":["Wallet"],"x-product":{"wallet":"Wallet"},"x-use":"GET /v3/wallet/transaction"}},"/v3/account":{"get":{"description":"Returns account details for the authenticated user. Personal data (name, surname, email,\nphone) is returned masked for privacy. The response includes the user's profile settings,\nverification state, company data (for business accounts), knowledge level and onboarding\nstatus.\n\nThe gateway injects the authenticated user's identity; the caller does not send it.\n","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"accountCompleted":{"type":"boolean"},"accountPurpose":{"enum":["savings","currencyExchange","investment","trading","cryptocurrencyPayments"],"type":"string"},"alias":{"pattern":"^[0-9a-z\\-_]{2,30}$","type":"string"},"company":{"properties":{"annualTradeEstimatedValue":{"type":"integer"},"attorneyInFact":{"properties":{"name":{"type":"string"},"numberOfDocument":{"maxLength":24,"type":"string"},"surname":{"type":"string"},"typeOfDocument":{"enum":["none","idcard","foreign-id-card","passport","drivinglicense","visa"],"type":"string"}},"type":"object"},"autonomus":{"type":"boolean"},"billingVolume":{"type":"integer"},"businessName":{"type":"string"},"constitutionCountryCode":{"pattern":"^[A-Z]{2}$","type":"string"},"constitutionDate":{"format":"date","type":"string"},"contact":{"properties":{"isPartner":{"type":"boolean"},"name":{"type":"string"},"numberOfDocument":{"maxLength":24,"type":"string"},"surname":{"type":"string"},"typeOfDocument":{"enum":["none","idcard","foreign-id-card","passport","drivinglicense","visa"],"type":"string"}},"type":"object"},"economicCapacityModel":{"enum":["model_200","model_390","model_303"],"type":"string"},"firstTradeEstimatedValue":{"type":"integer"},"identity":{"properties":{"countryCode":{"pattern":"^[A-Z]{2}$","type":"string"},"number":{"maxLength":24,"type":"string"},"type":{"enum":["none","idcard","passport","drivinglicense","visa","cif"],"type":"string"},"updatedAt":{"format":"date","type":"string"}},"type":"object"},"isSinglePartner":{"type":"boolean"},"kindOfSociety":{"type":"string"},"legalEntityId":{"maxLength":20,"type":"string"},"legalTerms":{"type":"boolean"},"numberOfPartners":{"type":"integer"},"obligedSubject":{"type":"boolean"},"otherServices":{"nullable":true,"type":"string"},"overTheCounter":{"type":"boolean"},"partners":{"items":{"properties":{"birthdate":{"format":"date","type":"string"},"deletedAt":{"format":"date","type":"string"},"documentCountryCode":{"pattern":"^[A-Z]{2}$","type":"string"},"documentExpirationDate":{"format":"date","type":"string"},"documentNumber":{"maxLength":24,"type":"string"},"documentType":{"enum":["none","idcard","foreign-id-card","passport","drivinglicense","visa"],"type":"string"},"isPoliticallyExposed":{"type":"boolean"},"name":{"type":"string"},"nationalityCountryCode":{"pattern":"^[A-Z]{2}$","type":"string"},"partnerId":{"pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"},"position":{"type":"string"},"sharePercentage":{"type":"number"},"surname":{"type":"string"}},"required":["partnerId"],"type":"object"},"type":"array"},"politicalPartners":{"items":{"properties":{"name":{"type":"string"},"position":{"type":"string"}},"required":["name","position"],"type":"object"},"type":"array"},"politicallyExposedPersonPartners":{"type":"boolean"},"reasonForTheOperation":{"items":{"type":"string"},"type":"array"},"registeredOffice":{"type":"string"},"sector":{"type":"string"},"service":{"type":"string"},"services":{"items":{"enum":["crypto_investment","send_crypto","liquidity","earn_loan","api","consulting","others"],"type":"string"},"type":"array"},"shareholdingStructure":{"nullable":true,"type":"string"},"taxId":{"maxLength":11,"type":"string"},"typeOfOperationsToPerform":{"items":{"type":"string"},"type":"array"},"webUrl":{"nullable":true,"type":"string"}},"type":"object"},"depositEstimation":{"properties":{"maximum":{"type":"integer"},"minimum":{"type":"integer"}},"required":["minimum","maximum"],"type":"object"},"documentValidity":{"description":"Identity document validity. May be absent for users with no recorded expiry date; an absent value does not invalidate the identity.","enum":["valid","almostExpired","expired","updateRequired"],"type":"string"},"email":{"format":"email","maxLength":96,"minLength":6,"type":"string"},"experienceLevel":{"enum":["beginner","intermediate","advanced"],"type":"string"},"fundsOrigin":{"properties":{"othersReason":{"type":"string"},"type":{"enum":["salary","incomes","pensions","propertiesSell","donations","investments","cryptoMining","others"],"type":"string"}},"required":["type"],"type":"object"},"hasSubaccountJunior":{"type":"boolean"},"id":{"pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"},"identityDocumentRemainingDays":{"description":"Days until account block at T+90 when documentValidity is almostExpired","type":"integer"},"knowledgeLevel":{"maximum":4,"minimum":1,"type":"integer"},"knowledgeQuestionsStatus":{"enum":["completed","uncompleted","omitted"],"type":"string"},"mainUserId":{"pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"},"person":{"properties":{"birthDate":{"format":"date","type":"string"},"gender":{"enum":["male","female","N/D"],"type":"string"},"name":{"maxLength":64,"type":"string"},"nationalityCountryCode":{"pattern":"^[A-Z]{2}$","type":"string"},"surname":{"maxLength":128,"type":"string"}},"type":"object"},"phone":{"properties":{"countryCode":{"pattern":"^[0-9]{1,4}$","type":"string"},"number":{"maxLength":32,"pattern":"^[0-9]+$","type":"string"}},"required":["number","countryCode"],"type":"object"},"profile":{"properties":{"avatar":{"properties":{"lg":{"type":"string"},"md":{"type":"string"},"sm":{"type":"string"}},"type":"object"},"currencyCode":{"pattern":"^[A-Z]{3}$","type":"string"},"langCode":{"pattern":"^[a-z]{2}(-[A-Z]{2})?$","type":"string"},"timeZone":{"format":"^[A-Za-z_\\-\\\\]+$","maxLength":50,"type":"string"}},"type":"object"},"realEmail":{"format":"email","maxLength":96,"minLength":6,"type":"string"},"registrationDate":{"format":"date","type":"string"},"registrationReason":{"enum":["investing","diversification","savings","curiosity","blockchain"],"type":"string"},"registrationResidenceCountry":{"pattern":"^[A-Z]{2}$","type":"string"},"secondFactorAuth":{"properties":{"alwaysRequired":{"type":"boolean"}},"type":"object"},"selfInvoiceIdentityNumber":{"maxLength":30,"type":"string"},"type":{"enum":["person","company","employee"],"type":"string"}},"required":["id","email"],"type":"object"}}},"description":"Account details for the authenticated user."},"404":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"User not found."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Get account details","tags":["Account"],"x-product":{"wallet":"Account"}}},"/v3/account/verify/identity/init":{"post":{"deprecated":true,"description":"**Deprecated** — use `POST /v3/verifier/identity-verification/init` instead.\n\nInitiates the identity verification process for the authenticated user. Returns\na redirect URL or token for the identity provider flow.\n","requestBody":{"content":{"application/json":{"example":{"documentType":"idcard","locale":"es","workflowId":10011},"schema":{"properties":{"documentType":{"description":"Type of identity document.","enum":["idcard","foreign-id-card","passport","drivinglicense"],"type":"string"},"errorUrl":{"description":"URL to redirect on error.","type":"string"},"locale":{"description":"User locale for the verification flow.","example":"es","type":"string"},"successUrl":{"description":"URL to redirect on success.","type":"string"},"workflowId":{"default":10011,"description":"Identity workflow ID.","enum":[10011],"type":"number"}},"required":["locale"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"provider":"incode","redirectUrl":"https://example.com/verify?token=abc123","reference":"ref-456","saved":true,"token":"abc123"},"schema":{"properties":{"provider":{"description":"Identity verification provider.","enum":["incode","didit"],"type":"string"},"redirectUrl":{"description":"URL to redirect the user for identity verification.","type":"string"},"reference":{"description":"Reference identifier for the verification process.","type":"string"},"saved":{"description":"Whether the verification state was persisted.","type":"boolean"},"token":{"description":"Token for the identity verification session.","type":"string"}},"type":"object"}}},"description":"Verification flow initiated."},"403":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Invalid credentials or user not allowed."},"404":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"User not found or user residence not found."},"406":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Retry limit exceeded."},"409":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Verification process already executed."},"412":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"User type not valid for this verification."},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Init identity verification (deprecated)","tags":["Verifier Deprecated Methods"],"x-product":{"wallet":"KYC"},"x-use":"POST /v3/verifier/identity-verification/init"}},"/v3/currency/chart":{"get":{"description":"Returns a time series for a currency pair, ready to draw a price chart.\n\nEach row is `[time, baseRate, quoteRate]`: Unix epoch milliseconds, then the rate of\neach currency against the US dollar (units per 1 USD, as in `GET /v1/currency/rate`).\nThe price of the base in the quote currency is `quoteRate / baseRate`. Either rate is\n`null` when there is no data at that timestamp; skip those rows instead of plotting\nzero.\n\n`temporality` selects both the time range and the spacing between points. Rows are\nordered oldest first.\n\n`all-time` is not available between two fiat currencies and returns a `400` with a\ndifferent body shape (`errorCode` instead of `statusCode`).\n\nNo authentication is required.\n","parameters":[{"description":"Currency pair as `BASE/QUOTE`, for example `BTC/EUR`. Both symbols must be known to the service. URL-encode the slash as `%2F` if your client does not do it.\n","example":"BTC/EUR","in":"query","name":"ticker","required":true,"schema":{"pattern":"^[\\w\\d]{1,}\\/[\\w\\d]{1,}$","type":"string"}},{"description":"Time range covered by the chart.","example":"one-day","in":"query","name":"temporality","required":true,"schema":{"enum":["one-hour","four-hours","twelve-hours","one-day","one-week","one-month","three-months","six-months","one-year","all-time"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"btcEurOneDay":{"summary":"`ticker=BTC/EUR\u0026temporality=one-day`, first rows","value":[[1788443280000,0.000012686031591522499,0.860151],[1788443640000,0.00001268453495745528,0.860151]]}},"schema":{"description":"Rows of `[time, baseRate, quoteRate]`. `time` is Unix epoch milliseconds. Each rate is how many units of that currency equal one US dollar, the same convention as `GET /v1/currency/rate`, so the price of the base in the quote currency is `quoteRate / baseRate`. A rate is `null` when no data exists for that timestamp.\n","example":[[1712497400000,0.0933,0.9855],[1712498400000,0.9222,0.9856],[1712499400000,0.9222,null]],"items":{"items":{"nullable":true,"type":"number"},"maxItems":3,"minItems":3,"type":"array"},"type":"array"}}},"description":"Chart rows ordered oldest to newest."},"400":{"content":{"application/json":{"examples":{"allTimeFiatToFiat":{"summary":"`temporality=all-time` with two fiat currencies, such as `EUR/USD`","value":{"date":"2026-09-25T08:00:00.000Z","errorCode":"B2M_CURRENCY_ALL_TIME_CHART_FIAT_TO_FIAT","errorType":"GENERIC","message":"Cannot get all time chart between two fiats","requestId":"3f1c2a4e-8b7d-4e61-9a0f-2c5d7e9b1a34"}},"invalidTicker":{"summary":"A symbol in `ticker` is not known to the service","value":{"error":"Bad Request","message":"invalid ticker parameter","statusCode":400}},"validation":{"summary":"`temporality` missing or not in the enum","value":{"error":"Bad Request","message":["temporality must be one of the following values: one-hour, four-hours, twelve-hours, one-day, one-week, one-month, three-months, six-months, one-year, all-time","temporality should not be empty"],"statusCode":400}}},"schema":{"oneOf":[{"description":"Error body produced by the currency service. `message` is a single string for business errors and an array of strings when the query fails validation. `error` is absent on a bare `404` and on unexpected `500` errors.\n","properties":{"error":{"description":"HTTP reason phrase, such as `Bad Request` or `Not Found`.","type":"string"},"message":{"description":"Error message, or one message per failed validation rule.","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"description":"HTTP status code, repeated in the body.","type":"integer"}},"required":["statusCode","message"],"type":"object"},{"properties":{"date":{"description":"When the error was produced (ISO 8601)","example":"2025-11-11T11:11:11.111Z","format":"date-time","type":"string"},"errorCode":{"description":"Stable, machine-readable error identifier. Branch on this, never on `message`.","example":"B2M_BLOCKCHAIN_MANAGER_TRAVEL_RULE_ORDER_NOT_FOUND","type":"string"},"errorType":{"enum":["GENERIC"],"type":"string"},"message":{"description":"Human-readable description of the error, intended for logs rather than end users.","example":"Travel rule order not found: 00000000-0000-4000-8000-000000000000","type":"string"},"requestId":{"description":"Identifier of the request that failed. Quote it when reporting an incident.","example":"be4dfe03-1a7f-4395-a846-eff56ab5d5bd","format":"uuid","type":"string"}},"required":["errorCode","message","errorType","date"],"type":"object"}]}}},"description":"Invalid parameters. Validation and unknown-symbol errors use the currency service shape; the fiat-to-fiat `all-time` rejection uses the errorpedia shape. Tell them apart by the presence of `errorCode`.\n"},"500":{"content":{"application/json":{"examples":{"internal":{"value":{"message":"Internal Server Error","statusCode":500}}},"schema":{"description":"Error body produced by the currency service. `message` is a single string for business errors and an array of strings when the query fails validation. `error` is absent on a bare `404` and on unexpected `500` errors.\n","properties":{"error":{"description":"HTTP reason phrase, such as `Bad Request` or `Not Found`.","type":"string"},"message":{"description":"Error message, or one message per failed validation rule.","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"description":"HTTP status code, repeated in the body.","type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"The chart could not be generated."}},"summary":"Get historic price chart","tags":["Currency"],"x-product":{"wallet":"Market"}}},"/v3/currency/ticker/{symbol}":{"get":{"description":"Returns the price and market statistics of one crypto asset in a chosen currency.\n\nThe response is a two-level map: the outer key is `rateCurrency` (or `USD` when it is\nomitted) and the inner key is the path `symbol`. The array under it depends on\n`interval`:\n\n- Without `interval`, one entry with the live quote and no `interval` field.\n- With `interval`, one entry per requested interval holding the price one interval ago,\n  and no live quote. Request the endpoint twice if you need both.\n\nMarket statistics (`marketCap`, `totalVolume`, `fullyDilutedMarketCap`, `maxSupply`,\n`totalSupply`) are always the current values, converted to `rateCurrency`, and are\nomitted when the service has no data for them.\n\nThe service does not reject unknown symbols. An unknown `symbol` returns `[null]`\n(without `interval`) or `[]` (with it), and an unknown `rateCurrency` returns\n`price: \"0\"`.\n\nNo authentication is required.\n","parameters":[{"description":"Crypto asset symbol, such as `BTC`. Case-sensitive.","example":"BTC","in":"path","name":"symbol","required":true,"schema":{"pattern":"^[A-Z0-9]{1,10}$","type":"string"}},{"description":"Currency to quote prices and market statistics in, fiat or crypto (for example `EUR` or `USDT`). Defaults to `USD`.\n","example":"EUR","in":"query","name":"rateCurrency","schema":{"pattern":"^[A-Z0-9]{2,10}$","type":"string"}},{"description":"Historical points to return instead of the live quote. Repeat the parameter or pass a comma-separated list; entries come back in the order requested.\n","example":["one_day"],"explode":true,"in":"query","name":"interval","schema":{"items":{"enum":["one_hour","one_day","one_week","one_month","one_year"],"type":"string"},"type":"array"},"style":"form"},{"deprecated":true,"description":"Accepted for compatibility but ignored: market statistics are always included when available.\n","in":"query","name":"extended","schema":{"type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"examples":{"btcInEurOneDay":{"summary":"`rateCurrency=EUR\u0026interval=one_day`","value":{"EUR":{"BTC":[{"fullyDilutedMarketCap":"1361236321483.54084","interval":"one_day","marketCap":"1361235304575.321375","maxSupply":"21000000","price":"66236.59258800412841517804095635","time":1788357343771,"totalSupply":"20079084","totalVolume":"22245259011.29535"}]}}},"unknownSymbol":{"summary":"Unknown symbol without `interval`","value":{"USD":{"XYZ":[null]}}}},"schema":{"additionalProperties":{"additionalProperties":{"items":{"anyOf":[{"properties":{"fullyDilutedMarketCap":{"description":"Fully diluted market capitalisation converted to `rateCurrency`. Absent when there is no data.","format":"number","nullable":true,"type":"string"},"interval":{"description":"Interval this entry belongs to. Absent on the live quote, which is only returned when no `interval` is requested.\n","enum":["one_hour","one_day","one_week","one_month","one_year"],"type":"string"},"marketCap":{"description":"Market capitalisation converted to `rateCurrency`. Absent when there is no data. The market fields are always current values, even on interval entries.\n","format":"number","nullable":true,"type":"string"},"maxSupply":{"description":"Maximum supply in units of the asset. `1e100000000` means the supply is unlimited. Absent when there is no data.\n","format":"number","nullable":true,"type":"string"},"price":{"description":"Price of one unit of the asset in `rateCurrency`, as a decimal string. `\"0\"` when either currency is unknown to the service.\n","format":"number","type":"string"},"time":{"description":"Unix epoch time in milliseconds.","format":"int64","type":"integer"},"totalSupply":{"description":"Total supply in units of the asset. Absent when there is no data.","format":"number","nullable":true,"type":"string"},"totalVolume":{"description":"Traded volume converted to `rateCurrency`. Absent when there is no data.","format":"number","nullable":true,"type":"string"}},"required":["time","price"],"type":"object"},{"enum":[null],"nullable":true,"type":"object"}]},"type":"array"},"type":"object"},"description":"Two-level map. The outer key is the requested `rateCurrency`, or `USD` when it is omitted. The inner key is the path `symbol`. The array holds one entry, or one per requested interval. For a symbol the service does not know, the array is `[null]` without `interval` and empty with it.\n","type":"object"}}},"description":"Ticker entries keyed by quote currency and asset symbol."},"400":{"content":{"application/json":{"examples":{"invalidInterval":{"value":{"error":"Bad Request","message":["each value in interval must be one of the following values: one_hour, one_day, one_week, one_month, one_year"],"statusCode":400}}},"schema":{"description":"Error body produced by the currency service. `message` is a single string for business errors and an array of strings when the query fails validation. `error` is absent on a bare `404` and on unexpected `500` errors.\n","properties":{"error":{"description":"HTTP reason phrase, such as `Bad Request` or `Not Found`.","type":"string"},"message":{"description":"Error message, or one message per failed validation rule.","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"description":"HTTP status code, repeated in the body.","type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"An `interval` value is not in the enum."},"500":{"content":{"application/json":{"examples":{"internal":{"value":{"message":"Internal server error","statusCode":500}}},"schema":{"description":"Error body produced by the currency service. `message` is a single string for business errors and an array of strings when the query fails validation. `error` is absent on a bare `404` and on unexpected `500` errors.\n","properties":{"error":{"description":"HTTP reason phrase, such as `Bad Request` or `Not Found`.","type":"string"},"message":{"description":"Error message, or one message per failed validation rule.","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"statusCode":{"description":"HTTP status code, repeated in the body.","type":"integer"}},"required":["statusCode","message"],"type":"object"}}},"description":"Unexpected error in the currency service."}},"summary":"Get ticker data for one asset","tags":["Currency"],"x-product":{"wallet":"Market"}}},"/v3/signin/sfa":{"get":{"description":"Checks the active two-factor authentication methods for the authenticated user and\ninitiates the verification process. When `sfaType` is phone-based (`sms`, `call`,\n`whatsapp`) the service sends the OTP code immediately and returns a\n`retryIntervalSeconds` countdown.\n\nOptionally accepts an `operation` query parameter to scope the 2FA challenge to a\nspecific action (e.g. withdrawal, email change).\n","parameters":[{"description":"Scopes the 2FA challenge to a specific action.","in":"query","name":"operation","schema":{"enum":["sfa.withdrawal","sfa.emailModification","sfa.phoneModification","sfa.personalDataAccess","sfa.login"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"gauth":{"summary":"Google Authenticator","value":{"codeLength":6,"sfaType":"gauth"}},"sms":{"summary":"SMS OTP","value":{"availableChannels":["sms","whatsapp"],"codeLength":4,"defaultChannel":"sms","retryIntervalSeconds":60,"sfaType":"sms"}}},"schema":{"allOf":[{"properties":{"availableChannels":{"description":"Phone OTP channels available for the current user","items":{"enum":["sms","call","whatsapp"],"type":"string"},"type":"array"},"defaultChannel":{"enum":["sms","call","whatsapp"],"type":"string"}},"type":"object"},{"properties":{"codeLength":{"type":"integer"},"retryIntervalSeconds":{"type":"integer"},"sfaType":{"enum":["gauth","sms","email","call","whatsapp"],"type":"string"}},"required":["sfaType"],"type":"object"}]}}},"description":"SFA process initiated. Returns the active method and retry metadata."},"400":{"content":{"application/json":{"schema":{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"}}},"description":"Bad request — invalid operation value."},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."},"404":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"User not found."},"429":{"content":{"application/json":{"example":{"error":"Too Many Requests","message":"rateLimitRemaining","statusCode":429},"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Rate limit exceeded (Twilio). The `message` field contains\n`rateLimitRemaining` and `retryIntervalSeconds`.\n"},"default":{"content":{"application/json":{"schema":{"properties":{"data":{"type":"object"},"error":{"type":"string"},"message":{"type":"string"},"reqId":{"type":"string"},"statusCode":{"type":"number"}},"required":["message","error"],"type":"object"}}},"description":"Unexpected error."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"Check and start two-factor verification","tags":["Auth"],"x-product":{"wallet":"Access"}}},"/v3/wallet/transaction":{"get":{"description":"Returns the movements of the authenticated user's wallet, newest first, one page at a time.\n\nTo read the next page, send the `pageInfo.endCursor` of the previous response as `cursor`\nand keep the same filters. Stop when `pageInfo.hasNextPage` is `false`; `endCursor` is\n`null` only when the page is empty.\n\nAll filters are optional and combine with AND. Each item has the shape of\n`GET /v1/wallet/transaction/{id}` without the details: the fees, the user's note and the\namounts valued in another currency are only returned there.\n\nBuys, sells and swaps appear only once they are `completed`, and a transfer between two\ndifferent users appears as a `withdrawal` to the sender and as a `deposit` to the receiver.\n","parameters":[{"description":"Position to continue from: the `pageInfo.endCursor` of the previous page. Omit it to get\nthe first page. Treat it as opaque; a value that was not returned by this endpoint is\nrejected with `400`.\n","in":"query","name":"cursor","schema":{"example":"eyJjcmVhdGVkQXQiOiIyMDI0LTAzLTI3VDA5OjEyOjQ0LjEyMFoifQ==","minLength":1,"type":"string"}},{"description":"Maximum number of transactions in the page.","in":"query","name":"limit","schema":{"default":20,"example":20,"maximum":100,"minimum":1,"type":"integer"}},{"description":"Only transactions created during this calendar year. A year later than the current one\nis rejected with `400`.\n","in":"query","name":"year","schema":{"example":2024,"type":"integer"}},{"description":"Only transactions that move this asset, as origin or as destination.","in":"query","name":"currency","schema":{"example":"BTC","type":"string"}},{"description":"Only one kind of operation. Without it, every transaction of the user is listed.\n\n- `purchase`: buys, paid with an external payment method or from a pocket, and Launchpad\n  purchases.\n- `sell`: sells from a pocket.\n- `swap`: swaps between two pockets.\n- `deposit`: fiat deposits (card, Google Pay, bank transfer, Tikebit and manual ones),\n  referral rewards and profit sharing, and funds sent to Launchpad.\n- `withdrawal`: withdrawals to a bank account or card, manual withdrawals, and funds\n  returned from Launchpad.\n- `deposit-earn`: funds sent from the wallet to Earn.\n- `withdrawal-earn`: funds returned from Earn to the wallet.\n- `deposit-trading`: funds received in the wallet from the Pro trading account.\n- `withdrawal-trading`: funds sent from the wallet to the Pro trading account.\n- `send-pay`: Social Pay payments sent by email, phone or alias.\n- `receive-pay`: Social Pay payments received by email, phone or alias.\n- `purchase-bcard`: Bit2Me Card payments.\n- `reimburse-bcard`: Bit2Me Card refunds.\n- `send`: crypto sent to another user's Bit2Me address or to an external address.\n- `receive`: crypto received from another user's Bit2Me address or from the blockchain,\n  and vesting releases.\n","in":"query","name":"operation","schema":{"enum":["purchase","sell","swap","deposit","withdrawal","deposit-earn","withdrawal-earn","deposit-trading","withdrawal-trading","send-pay","receive-pay","purchase-bcard","reimburse-bcard","send","receive"],"example":"purchase","type":"string"}},{"description":"Only transactions linked to this payment order, the `orders.tellerId` of a transaction.","in":"query","name":"tellerId","schema":{"example":"a1b2c3d4-e5f6-4890-abcd-ef1234567890","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"empty":{"summary":"Nothing matches the filters, or the previous page was the last one","value":{"data":[],"pageInfo":{"endCursor":null,"hasNextPage":false}}},"page":{"summary":"A page with more results after it","value":{"data":[{"canceledAt":null,"completedAt":"2024-03-28T13:06:19.411Z","concept":"","date":"2024-03-28T13:06:18.032Z","denomination":{"amount":"100.00000000","currency":"EUR","rate":{"extraDecimals":"0","pair":{"base":"EUR","quote":"EUR"},"value":"1.00000000"}},"destination":{"address":null,"addressInBlacklist":null,"addressNetwork":null,"addressTag":null,"amount":"0.00178266","class":"pocket","currency":"BTC","pocketId":"eb775a29-365d-4881-b7b9-1fa66fe1eb4d","pocketName":"Bitcoin savings","rate":{"extraDecimals":"0","pair":{"base":"BTC","quote":"EUR"},"value":"55535.00000000"}},"frequency":"punctual","id":"f040acdf-62b0-4040-9574-655fdcf7e541","instantId":"2be1f76b-9332-4e96-9e58-8f9d65206b02","isInitialRecurringOrder":false,"method":"pocket","origin":{"amount":"100.00000000","class":"pocket","currency":"EUR","pocketId":"9ca6cf96-4645-4658-b086-6cdb367c16bd","pocketName":"Euro pocket","rate":{"extraDecimals":"0","pair":{"base":"EUR","quote":"EUR"},"value":"1.00000000"}},"status":"completed","subtype":"purchase","type":"transfer","updatedAt":"2024-03-28T13:06:19.411Z"},{"canceledAt":null,"completedAt":"2024-03-27T09:31:02.000Z","concept":"","date":"2024-03-27T09:12:44.120Z","denomination":{"amount":"0.01000000","currency":"BTC","rate":{"extraDecimals":"0","pair":{"base":"BTC","quote":"BTC"},"value":"1.00000000"}},"destination":{"address":"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq","addressInBlacklist":false,"addressNetwork":"bitcoin","addressTag":null,"amount":"0.01000000","class":"blockchain","currency":"BTC","pocketId":null,"pocketName":null},"frequency":"punctual","id":"3c1f9a7e-2b4d-4e8f-9a61-7d5e0c2b8f14","isInitialRecurringOrder":false,"method":"blockchain","origin":{"amount":"0.01002000","class":"pocket","currency":"BTC","pocketId":"eb775a29-365d-4881-b7b9-1fa66fe1eb4d","pocketName":"Bitcoin savings"},"status":"completed","subtype":"automatic-send","transaction":{"confirmationCount":3,"confirmedAt":"2024-03-27T09:31:02.000Z"},"type":"withdrawal","updatedAt":"2024-03-27T09:31:02.000Z"}],"pageInfo":{"endCursor":"eyJjcmVhdGVkQXQiOiIyMDI0LTAzLTI3VDA5OjEyOjQ0LjEyMFoifQ==","hasNextPage":true}}}},"schema":{"properties":{"data":{"description":"The transactions of the page. Empty when nothing matches.","items":{"description":"A movement of funds in the user's wallet, seen from the user's side.\n\n`type`, `subtype` and `method` together say what the movement was, and `origin.class` and\n`destination.class` say what each side is, which in turn tells which of their fields are\nfilled. A transfer between two different users is shown as a `withdrawal` to the sender and\nas a `deposit` to the receiver.\n\nAmounts are decimal strings padded to the precision of their currency.\n","properties":{"canceledAt":{"description":"When the transaction was cancelled (ISO 8601). `null` unless it was cancelled.","format":"date-time","nullable":true,"type":"string"},"company":{"description":"Present only on bank withdrawals: the amount paid out to the bank account, in the\ncurrency of the Bit2Me entity that serves the user, with the rate used.\n","properties":{"destination":{"description":"Amount the bank account receives.","properties":{"amount":{"description":"Amount paid out, as a decimal string.","example":"41.00000000","type":"string"},"currency":{"description":"Currency the withdrawal is paid out in.","example":"EUR","type":"string"},"rate":{"allOf":[{"description":"The exchange rate applied, expressed as how much of `pair.quote` one unit of `pair.base` was\nworth at the time.\n","properties":{"extraDecimals":{"description":"Extra decimal places `value` should be shifted by, as a decimal string. Almost always\n`'0'`; it is non-zero only for assets whose price needs more precision than `value`\nalone carries.\n","example":"0","type":"string"},"pair":{"description":"Which two assets the rate relates.","properties":{"base":{"type":"string"},"quote":{"type":"string"}},"required":["base","quote"],"type":"object"},"value":{"allOf":[{"maxLength":50,"minLength":1,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}],"description":"The rate, as a decimal string.","example":"55535.00000000"}},"required":["value","pair"],"type":"object"}],"description":"Rate used to convert the withdrawn amount into `currency`."}},"required":["currency","amount","rate"],"type":"object"}},"type":"object"},"completedAt":{"description":"When the transaction was completed (ISO 8601). `null` until it is.","example":"2024-03-28T13:06:19.411Z","format":"date-time","nullable":true,"type":"string"},"concept":{"description":"Short description of the transaction, as set when it was created. An empty string when\nnone was set, which is frequent.\n","example":"","type":"string"},"date":{"description":"When the transaction was created (ISO 8601). Lists are sorted by it, newest first.","example":"2024-03-28T13:06:18.032Z","format":"date-time","type":"string"},"denomination":{"description":"The amount and currency the user expressed the operation in when creating it (the\n`amount` and `currency` of the proforma), with the rate of that currency at the time.\nOmitted on movements that do not have one.\n","properties":{"amount":{"description":"Amount the operation was requested for, as a decimal string.","example":"100.00000000","type":"string"},"currency":{"description":"Currency `amount` is expressed in.","example":"EUR","type":"string"},"rate":{"allOf":[{"description":"The exchange rate applied, expressed as how much of `pair.quote` one unit of `pair.base` was\nworth at the time.\n","properties":{"extraDecimals":{"description":"Extra decimal places `value` should be shifted by, as a decimal string. Almost always\n`'0'`; it is non-zero only for assets whose price needs more precision than `value`\nalone carries.\n","example":"0","type":"string"},"pair":{"description":"Which two assets the rate relates.","properties":{"base":{"type":"string"},"quote":{"type":"string"}},"required":["base","quote"],"type":"object"},"value":{"allOf":[{"maxLength":50,"minLength":1,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}],"description":"The rate, as a decimal string.","example":"55535.00000000"}},"required":["value","pair"],"type":"object"}],"description":"Rate between `currency` and the currency of the origin pocket when the operation was\ncreated. When both are the same it is `1`, with that currency on both sides of `pair`.\n"}},"type":"object"},"destination":{"allOf":[{"description":"One side of a transaction, either where the funds came from (`origin`) or where they went\n(`destination`).\n\nWhich properties are filled depends on `class`. The two sides do not carry the same keys:\n\n- Both sides always have `class`, `amount` and `currency`, and usually `pocketId` and\n  `pocketName`, which are `null` when the side is not one of the user's pockets.\n- Only `destination` carries `address`, `addressNetwork`, `addressTag` and\n  `addressInBlacklist`, present and `null` when they do not apply.\n- When the counterparty was addressed by email, phone or alias, its `pocketId` and\n  `pocketName` are omitted, and `email`, `phone`, `alias` or `fullName` take their place.\n- A Launchpad destination only carries `class`, `amount`, `currency` and `rate`.\n","properties":{"address":{"description":"Blockchain address of the movement, on `destination` only. `null` when the movement has no address.","example":"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq","nullable":true,"type":"string"},"addressInBlacklist":{"description":"Whether the address is flagged as high risk. `null` when there is no address or the check\ndoes not apply.\n","example":false,"nullable":true,"type":"boolean"},"addressNetwork":{"description":"Network id the address belongs to, for instance `bitcoin`. `null` when there is no\naddress.\n","example":"bitcoin","nullable":true,"type":"string"},"addressTag":{"description":"Destination tag or memo used with the address, on networks that route deposits with one.\n`null` when there is none.\n","nullable":true,"type":"string"},"alias":{"description":"Alias the receiver was addressed by, on the `destination` of a payment sent with `class` `alias`.","example":"janedoe","nullable":true,"type":"string"},"amount":{"description":"Amount moved on this side, as a decimal string. It differs between the two sides on any\ntransaction that converts or charges a fee, so read both rather than assuming they match.\n","example":"100.00000000","type":"string"},"bankAccount":{"description":"Bank account (usually an IBAN) at this side. Present on the `origin` of bank deposits and\non the `destination` of bank withdrawals; omitted otherwise.\n","example":"ES0000000000000000000000","nullable":true,"type":"string"},"class":{"description":"What kind of endpoint this side of the transaction is, which tells you which of the other\nfields are filled:\n\n- `pocket`: one of the user's own pockets, so `pocketId` and `pocketName` are set.\n- `trading`: the user's Pro trading account. It has no pocket, so `pocketId` and\n  `pocketName` are `null`.\n- `earn`: Earn, in the same way as `trading`.\n- `blockchain`: an on-chain send or receive; the address is on `destination`.\n- `b2m`: another Bit2Me user reached through one of its Bit2Me addresses. Its pocket\n  fields are `null`.\n- `email`, `phone`, `alias`: another user addressed by email, phone or alias.\n- `bankAccount`: a bank account, on the `destination` of a bank withdrawal.\n- `launchpad`, `vesting`: a Launchpad sale or a vesting release.\n- `bcard`: the Bit2Me Card.\n- On the `origin` of a deposit, the payment method used: `card`, `bank-transfer`,\n  `google-pay`, `apple-pay`, `paypal`, `hub-latam`, `cvu`, `bizum`, `mbway`, `tikebit`,\n  `manual`, `b2m-card`, `promo-referral` or `profit-share`.\n\nNew values may appear with new products, so treat an unknown value as an opaque string.\n","enum":["pocket","trading","earn","blockchain","b2m","alias","email","phone","bankAccount","launchpad","vesting","bcard","card","bank-transfer","google-pay","apple-pay","paypal","hub-latam","cvu","bizum","mbway","tikebit","manual","b2m-card","promo-referral","profit-share"],"example":"pocket","type":"string"},"currency":{"description":"The asset moved on this side.","example":"EUR","type":"string"},"email":{"description":"Email the receiver was addressed by, on the `destination` of a payment sent with `class` `email`.","example":"jane.doe@example.com","nullable":true,"type":"string"},"fullName":{"description":"Name of the sender, on the `origin` of a payment the user received by email, phone or\nalias, and on some deposits when it is known. Omitted otherwise.\n","example":"Jane Doe","nullable":true,"type":"string"},"phone":{"allOf":[{"description":"Phone number split into country calling code and national number.","properties":{"countryCode":{"description":"Country calling code, without the leading `+`.","example":34,"maximum":999,"minimum":1,"type":"integer"},"number":{"description":"National number, without the country calling code.","example":600000000,"format":"int64","minimum":0,"type":"integer"}},"type":"object"}],"description":"Phone the receiver was addressed by, on the `destination` of a payment sent with `class` `phone`."},"pocketId":{"description":"Identifier of the pocket at this side. `null` when this side is not one of the user's pockets.","example":"9ca6cf96-4645-4658-b086-6cdb367c16bd","format":"uuid","nullable":true,"type":"string"},"pocketName":{"description":"Name of the pocket at this side, as the user named it. `null` when this side is not one\nof the user's pockets, for instance the Pro trading account or a blockchain address.\n","example":"Euro pocket","nullable":true,"type":"string"},"queryParams":{"additionalProperties":{"type":"string"},"description":"Memo sent with a withdrawal to an address, as given in `queryParams` when the proforma\nwas created. Present only on `destination`, and only when one was given.\n","example":{"memoId":"123456"},"type":"object"},"rate":{"allOf":[{"description":"The exchange rate applied, expressed as how much of `pair.quote` one unit of `pair.base` was\nworth at the time.\n","properties":{"extraDecimals":{"description":"Extra decimal places `value` should be shifted by, as a decimal string. Almost always\n`'0'`; it is non-zero only for assets whose price needs more precision than `value`\nalone carries.\n","example":"0","type":"string"},"pair":{"description":"Which two assets the rate relates.","properties":{"base":{"type":"string"},"quote":{"type":"string"}},"required":["base","quote"],"type":"object"},"value":{"allOf":[{"maxLength":50,"minLength":1,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}],"description":"The rate, as a decimal string.","example":"55535.00000000"}},"required":["value","pair"],"type":"object"}],"description":"Value of one unit of `currency` in EUR at the time of the movement (`pair.base` is\n`currency`, `pair.quote` is `EUR`). Omitted when the movement has no rate.\n"},"userAmount":{"description":"`amount` converted to the `userCurrency` requested, valued at the date of the movement.\nOnly in `GET /v1/wallet/transaction/{id}` when `userCurrency` is sent.\n","properties":{"amount":{"description":"The converted amount, as a decimal string.","example":"99.00002310","type":"string"},"currency":{"description":"The `userCurrency` requested.","example":"EUR","type":"string"}},"required":["currency","amount"],"type":"object"}},"type":"object"}],"description":"Where the funds went."},"frequency":{"description":"How often the operation repeats. `punctual` is a one-off operation; the others belong to a\nrecurring order that runs every day, week or month. Movements with no frequency are reported\nas `punctual`.\n","enum":["punctual","daily","weekly","monthly"],"example":"punctual","type":"string"},"id":{"description":"Identifier of the transaction. Use it with `GET /v1/wallet/transaction/{id}`.","example":"f040acdf-62b0-4040-9574-655fdcf7e541","format":"uuid","type":"string"},"instantId":{"description":"Identifier of the conversion order behind the movement. Present only on movements that\nconverted one asset into another, such as buys, sells and swaps.\n","example":"2be1f76b-9332-4e96-9e58-8f9d65206b02","type":"string"},"isInitialRecurringOrder":{"description":"`true` when this movement is the first execution of a recurring order, the one run when\nthe order is created. `false` otherwise.\n","example":false,"type":"boolean"},"method":{"description":"How the funds moved. For an internal movement between the user's own pockets this is `pocket`;\nfor a blockchain send or receive it is `blockchain`; the rest identify the payment instrument\nor the way the counterparty was addressed.\n","enum":["alias","apple-pay","b2m-card","bank-transfer","bizum","blockchain","card","cvu","email","google-pay","hub-latam","launchpad","manual","mbway","paypal","phone","pocket","profit-share","promo-referral","redeem","redemption","tikebit"],"example":"pocket","type":"string"},"orders":{"allOf":[{"description":"Identifiers of the orders that produced the movement, to correlate it with an order created\nthrough another Bit2Me product. Each property is present only when that kind of order exists.\n","example":{"brokerageId":"f040acdf-62b0-4040-9574-655fdcf7e541","tellerId":"a1b2c3d4-e5f6-4890-abcd-ef1234567890"},"properties":{"blockchainManagerId":{"description":"Identifier of the blockchain order behind the movement, on some on-chain sends and receives.","example":"2be1f76b-9332-4e96-9e58-8f9d65206b02","format":"uuid","type":"string"},"brokerageId":{"description":"Identifier of the brokerage order behind the movement, such as an instant buy, sell or swap.","example":"f040acdf-62b0-4040-9574-655fdcf7e541","format":"uuid","type":"string"},"tellerId":{"description":"Identifier of the payment order behind the movement, such as a card purchase or a bank\nwithdrawal. It is the value accepted by the `tellerId` filter of the transaction lists.\n","example":"a1b2c3d4-e5f6-4890-abcd-ef1234567890","format":"uuid","type":"string"}},"type":"object"}],"description":"Identifiers of the orders that produced the movement. Omitted when there is none.\n"},"origin":{"allOf":[{"description":"One side of a transaction, either where the funds came from (`origin`) or where they went\n(`destination`).\n\nWhich properties are filled depends on `class`. The two sides do not carry the same keys:\n\n- Both sides always have `class`, `amount` and `currency`, and usually `pocketId` and\n  `pocketName`, which are `null` when the side is not one of the user's pockets.\n- Only `destination` carries `address`, `addressNetwork`, `addressTag` and\n  `addressInBlacklist`, present and `null` when they do not apply.\n- When the counterparty was addressed by email, phone or alias, its `pocketId` and\n  `pocketName` are omitted, and `email`, `phone`, `alias` or `fullName` take their place.\n- A Launchpad destination only carries `class`, `amount`, `currency` and `rate`.\n","properties":{"address":{"description":"Blockchain address of the movement, on `destination` only. `null` when the movement has no address.","example":"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq","nullable":true,"type":"string"},"addressInBlacklist":{"description":"Whether the address is flagged as high risk. `null` when there is no address or the check\ndoes not apply.\n","example":false,"nullable":true,"type":"boolean"},"addressNetwork":{"description":"Network id the address belongs to, for instance `bitcoin`. `null` when there is no\naddress.\n","example":"bitcoin","nullable":true,"type":"string"},"addressTag":{"description":"Destination tag or memo used with the address, on networks that route deposits with one.\n`null` when there is none.\n","nullable":true,"type":"string"},"alias":{"description":"Alias the receiver was addressed by, on the `destination` of a payment sent with `class` `alias`.","example":"janedoe","nullable":true,"type":"string"},"amount":{"description":"Amount moved on this side, as a decimal string. It differs between the two sides on any\ntransaction that converts or charges a fee, so read both rather than assuming they match.\n","example":"100.00000000","type":"string"},"bankAccount":{"description":"Bank account (usually an IBAN) at this side. Present on the `origin` of bank deposits and\non the `destination` of bank withdrawals; omitted otherwise.\n","example":"ES0000000000000000000000","nullable":true,"type":"string"},"class":{"description":"What kind of endpoint this side of the transaction is, which tells you which of the other\nfields are filled:\n\n- `pocket`: one of the user's own pockets, so `pocketId` and `pocketName` are set.\n- `trading`: the user's Pro trading account. It has no pocket, so `pocketId` and\n  `pocketName` are `null`.\n- `earn`: Earn, in the same way as `trading`.\n- `blockchain`: an on-chain send or receive; the address is on `destination`.\n- `b2m`: another Bit2Me user reached through one of its Bit2Me addresses. Its pocket\n  fields are `null`.\n- `email`, `phone`, `alias`: another user addressed by email, phone or alias.\n- `bankAccount`: a bank account, on the `destination` of a bank withdrawal.\n- `launchpad`, `vesting`: a Launchpad sale or a vesting release.\n- `bcard`: the Bit2Me Card.\n- On the `origin` of a deposit, the payment method used: `card`, `bank-transfer`,\n  `google-pay`, `apple-pay`, `paypal`, `hub-latam`, `cvu`, `bizum`, `mbway`, `tikebit`,\n  `manual`, `b2m-card`, `promo-referral` or `profit-share`.\n\nNew values may appear with new products, so treat an unknown value as an opaque string.\n","enum":["pocket","trading","earn","blockchain","b2m","alias","email","phone","bankAccount","launchpad","vesting","bcard","card","bank-transfer","google-pay","apple-pay","paypal","hub-latam","cvu","bizum","mbway","tikebit","manual","b2m-card","promo-referral","profit-share"],"example":"pocket","type":"string"},"currency":{"description":"The asset moved on this side.","example":"EUR","type":"string"},"email":{"description":"Email the receiver was addressed by, on the `destination` of a payment sent with `class` `email`.","example":"jane.doe@example.com","nullable":true,"type":"string"},"fullName":{"description":"Name of the sender, on the `origin` of a payment the user received by email, phone or\nalias, and on some deposits when it is known. Omitted otherwise.\n","example":"Jane Doe","nullable":true,"type":"string"},"phone":{"allOf":[{"description":"Phone number split into country calling code and national number.","properties":{"countryCode":{"description":"Country calling code, without the leading `+`.","example":34,"maximum":999,"minimum":1,"type":"integer"},"number":{"description":"National number, without the country calling code.","example":600000000,"format":"int64","minimum":0,"type":"integer"}},"type":"object"}],"description":"Phone the receiver was addressed by, on the `destination` of a payment sent with `class` `phone`."},"pocketId":{"description":"Identifier of the pocket at this side. `null` when this side is not one of the user's pockets.","example":"9ca6cf96-4645-4658-b086-6cdb367c16bd","format":"uuid","nullable":true,"type":"string"},"pocketName":{"description":"Name of the pocket at this side, as the user named it. `null` when this side is not one\nof the user's pockets, for instance the Pro trading account or a blockchain address.\n","example":"Euro pocket","nullable":true,"type":"string"},"queryParams":{"additionalProperties":{"type":"string"},"description":"Memo sent with a withdrawal to an address, as given in `queryParams` when the proforma\nwas created. Present only on `destination`, and only when one was given.\n","example":{"memoId":"123456"},"type":"object"},"rate":{"allOf":[{"description":"The exchange rate applied, expressed as how much of `pair.quote` one unit of `pair.base` was\nworth at the time.\n","properties":{"extraDecimals":{"description":"Extra decimal places `value` should be shifted by, as a decimal string. Almost always\n`'0'`; it is non-zero only for assets whose price needs more precision than `value`\nalone carries.\n","example":"0","type":"string"},"pair":{"description":"Which two assets the rate relates.","properties":{"base":{"type":"string"},"quote":{"type":"string"}},"required":["base","quote"],"type":"object"},"value":{"allOf":[{"maxLength":50,"minLength":1,"pattern":"^[0-9]+(\\.[0-9]+)?$","type":"string"}],"description":"The rate, as a decimal string.","example":"55535.00000000"}},"required":["value","pair"],"type":"object"}],"description":"Value of one unit of `currency` in EUR at the time of the movement (`pair.base` is\n`currency`, `pair.quote` is `EUR`). Omitted when the movement has no rate.\n"},"userAmount":{"description":"`amount` converted to the `userCurrency` requested, valued at the date of the movement.\nOnly in `GET /v1/wallet/transaction/{id}` when `userCurrency` is sent.\n","properties":{"amount":{"description":"The converted amount, as a decimal string.","example":"99.00002310","type":"string"},"currency":{"description":"The `userCurrency` requested.","example":"EUR","type":"string"}},"required":["currency","amount"],"type":"object"}},"type":"object"}],"description":"Where the funds came from."},"status":{"description":"Where the transaction is in its lifecycle.\n\n`completed`, `canceled`, `rejected`, `expired`, `refunded` and `error` are final. Everything\nelse is still in progress and will change on its own, so a client that polls should stop only\non a final status. `pending_user_information` means the user has to provide some information\nbefore the movement can go on.\n\nNote the inconsistent spelling of `pending_user_information`: it is the single status written\nwith underscores instead of hyphens.\n","enum":["pending","processing","reviewing","pending-review","awaiting-antifraud-decision","pending_user_information","completed","canceled","rejected","expired","refunded","error"],"example":"completed","type":"string"},"subtype":{"description":"What the transaction was for. Together with `type` it identifies the operation: a `deposit`\nwith subtype `trading` is money coming back from the Pro account, while a `withdrawal` with\nsubtype `trading` is money going into it.\n\nThe list is long because it accumulates every product that has ever moved funds, and new\nvalues are added as products appear. Treat an unknown subtype as an opaque string rather than\nfailing on it.\n","enum":["affiliates","airdrop","automatic-funding","automatic-send","bcard","birthday2me","card-purchase","earn","external","funding","futures","inactive-fee","junior","launchpad","launchpad-purchase","loan","loan-rectification","manual-send","manual-transfer","migration","otc","otc-buy","otc-sell","otc-swap","promo","purchase","receive","rectification","redeem","refund","reimbursement","safeguard-interest","seizures","sell","social-pay","stocks","swap","trading","transfer","vesting"],"example":"purchase","type":"string"},"transaction":{"description":"On-chain details. Present only when the movement has a blockchain transaction or was\ncharged a network fee.\n","properties":{"confirmationCount":{"description":"Number of confirmations seen for the blockchain transaction.","example":3,"format":"int32","minimum":0,"type":"integer"},"confirmedAt":{"description":"When the blockchain transaction was confirmed (ISO 8601). `null` until then.","example":"2024-03-27T09:31:02.000Z","format":"date-time","nullable":true,"type":"string"}},"type":"object"},"type":{"description":"Type of the transaction","enum":["deposit","transfer","withdrawal"],"example":"transfer","type":"string"},"updatedAt":{"description":"When the transaction record last changed (ISO 8601). It also moves when only the user's\nnote is edited, so it is not a reliable signal that the transaction itself progressed.\n","example":"2024-03-28T13:06:19.411Z","format":"date-time","type":"string"}},"required":["id","date","type","subtype","method","concept","origin","destination","status"],"type":"object"},"type":"array"},"pageInfo":{"description":"Where the page ends and whether there is more to read.","properties":{"endCursor":{"description":"Cursor to send as `cursor` to read the next page. `null` only when `data` is empty.","example":"eyJjcmVhdGVkQXQiOiIyMDI0LTAzLTI3VDA5OjEyOjQ0LjEyMFoifQ==","nullable":true,"type":"string"},"hasNextPage":{"description":"Whether more transactions match after this page.","example":true,"type":"boolean"}},"required":["hasNextPage","endCursor"],"type":"object"}},"required":["data","pageInfo"],"type":"object"}}},"description":"One page of transactions, newest first."},"400":{"content":{"application/json":{"examples":{"invalidCursor":{"summary":"cursor that was not returned by this endpoint","value":{"data":{},"error":"Bad Request","message":"Invalid cursor: not-a-cursor","statusCode":400}},"invalidYear":{"summary":"year later than the current one","value":{"data":{},"error":"Bad Request","message":"invalid year","statusCode":400}},"limitOutOfRange":{"summary":"limit above 100","value":{"errors":[{"code":"INVALID_REQUEST_PARAMETER","errors":[{"code":"MAXIMUM","message":"Value 500 is greater than maximum 100","params":[500,100],"path":[]}],"in":"query","message":"Invalid parameter (limit): Value failed JSON Schema validation","name":"limit"}],"message":"Validation errors"}}},"schema":{"oneOf":[{"description":"Returned with `400` when a request fails schema validation against the published contract.\nEvery violation is reported at once, so `errors` may hold several entries.\n","properties":{"errors":{"description":"One entry per parameter that failed validation.","items":{"description":"A single parameter that failed validation, with the individual violations found in it.","properties":{"code":{"description":"Category of the failure.","example":"INVALID_REQUEST_PARAMETER","type":"string"},"errors":{"description":"The concrete violations found in this parameter.","items":{"description":"One concrete schema violation.","properties":{"code":{"description":"Kind of violation. The values seen in practice are\n`REQUIRED` for an absent required query or path parameter,\n`OBJECT_MISSING_REQUIRED_PROPERTY` for an absent required field inside a body,\n`ENUM_MISMATCH` for a value outside the allowed set,\n`PATTERN` for a string that does not match the declared pattern,\n`MAX_LENGTH` for a string longer than allowed,\n`MAXIMUM` for a number above the declared maximum,\nand `INVALID_TYPE` for a wrong JSON type.\n","example":"PATTERN","type":"string"},"description":{"description":"Description of the parameter, copied from the OpenAPI document when available.","example":"The order ID or the wallet proforma ID","type":"string"},"message":{"description":"Human-readable description of the violation.","example":"String does not match pattern ^[0-9a-fA-F]{8}-...: nope","type":"string"},"params":{"description":"Arguments of the violation. Its meaning depends on `code`: the offending value for\n`ENUM_MISMATCH`, the missing field name for `OBJECT_MISSING_REQUIRED_PROPERTY`, the\nexpected pattern followed by the offending value for `PATTERN`, and the offending size\nfollowed by the allowed one for `MAX_LENGTH` and `MAXIMUM`.\n\nEntries are not always strings: the size-related codes report numbers.\n","example":["nope"],"items":{},"type":"array"},"path":{"description":"Path to the offending field inside the parameter, empty when the parameter itself is at\nfault. For a body, `[\"method\", \"type\"]` points at `method.type`.\n","example":["method","type"],"items":{"type":"string"},"type":"array"}},"required":["code","message"],"type":"object"},"type":"array"},"in":{"description":"Where the offending parameter was read from.","enum":["body","query","path","header"],"example":"query","type":"string"},"message":{"description":"Summary of what was rejected.","example":"Invalid parameter (id): Value failed JSON Schema validation","type":"string"},"name":{"description":"Name of the offending parameter. For a request body this is `data`.","example":"id","type":"string"},"path":{"description":"Location of the parameter inside the service's own OpenAPI document. It is an internal\npointer, useful for reporting a problem but not something to parse.\n","example":["paths","/v1/order/status","get","parameters","0"],"items":{"type":"string"},"type":"array"}},"required":["code","message","in","errors"],"type":"object"},"type":"array"},"message":{"description":"Always the constant `Validation errors`.","example":"Validation errors","type":"string"}},"required":["message","errors"],"type":"object"},{"description":"Error returned by the wallet operations.","properties":{"data":{"additionalProperties":true,"description":"Extra details about the error, `{}` when there are none. On the operations that say so,\nit holds a copy of the whole error, with the details under `data.data`.\n","example":{},"type":"object"},"error":{"description":"Reason phrase of the HTTP status.","example":"Not Found","type":"string"},"message":{"description":"What went wrong. Each operation lists the messages it can return.","example":"pocket not found","type":"string"},"statusCode":{"description":"Repeats the HTTP status code.","example":404,"maximum":499,"minimum":400,"type":"integer"}},"required":["statusCode","error","message"],"type":"object"}]}}},"description":"The request was rejected. Two shapes are possible:\n\n- A parameter outside its declared constraints (`limit` out of range, an unknown\n  `operation`, a `tellerId` that is not a lowercase UUID, a `year` that is not an\n  integer) answers `RequestValidationErrorResponse`.\n- A `year` later than the current one (`invalid year`) or a `cursor` that is not valid\n  (`Invalid cursor: \u003ccursor\u003e` or `Invalid cursor format: \u003ccursor\u003e`) answers\n  `WalletErrorResponse`.\n"},"403":{"content":{"application/json":{"example":{"code":403,"description":"invalid credentials"},"schema":{"description":"Returned with `403` when the request is rejected before being processed at all: the API key,\nthe signature or the nonce could not be validated. It is deliberately vague about which one\nfailed.\n\nNote the status is `403` and not `401`, and that this envelope shares no field with any other\nerror shape in the API.\n","properties":{"code":{"description":"Repeats the HTTP status code.","enum":[403],"example":403,"type":"integer"},"description":{"description":"Fixed message; it never carries detail about the specific failure.","example":"invalid credentials","type":"string"}},"required":["code","description"],"type":"object"}}},"description":"Invalid credentials."}},"security":[{"JwtAuth":[]},{"ApiKeyAuth":[]}],"summary":"List the user's wallet transactions (cursor pagination)","tags":["Wallet"],"x-product":{"wallet":"Wallet"}}}},"tags":[{"name":"Account"},{"name":"Accounting"},{"name":"Affiliates"},{"name":"Auth"},{"name":"Blockchain Manager"},{"name":"Brokerage"},{"name":"Captcha"},{"name":"Card"},{"name":"Card Authorizator"},{"name":"Card Loyalty"},{"name":"Crypto Credentials"},{"name":"Collection Orders"},{"name":"Compliance"},{"name":"Commerce"},{"name":"Configuration"},{"name":"Currency"},{"name":"Currency Analytics"},{"name":"Currency Collections"},{"name":"Currency Favorites"},{"name":"Earn"},{"name":"ExternalOnboarding"},{"name":"Instant"},{"name":"Junior"},{"name":"Launchpad"},{"name":"Loan"},{"name":"Misc"},{"name":"Notification"},{"name":"Portfolio"},{"name":"Portfolio Analytics"},{"name":"Price Alert Scheduler"},{"name":"Price Orders"},{"name":"Price Watchdog"},{"name":"Promotion"},{"name":"Recurring Orders"},{"name":"Support"},{"name":"Taxes"},{"name":"Teller"},{"name":"Terms and Conditions"},{"name":"Travel Rule"},{"name":"Trading"},{"name":"Translations"},{"name":"UX"},{"name":"Wallet"},{"name":"Stocks"},{"name":"Verifier"},{"name":"Pay"},{"name":"Space Center"},{"name":"Redeem Token"},{"name":"Account Deprecated Methods"},{"name":"Auth Deprecated Methods"},{"name":"Currency Deprecated Methods"},{"name":"Earn Deprecated Methods"},{"name":"Verifier Deprecated Methods"},{"description":"# Introduction\n\n👏 Welcome to Bit2Me as API.\n\n\nWe help individuals, exchanges, mining pools, tokens issuers, investment funds, governments and institutions\nto access, trade and manage cryptocurrencies and digital assets optimally.\n\n\nBeing the access door to markets without friction, leaving obsolete the traditional financial system, the\ncompany is made up of more than 300 people: idealists, technological entrepreneurs, researchers, quantitative,\nfinancial traders, lawyers and engineers from large companies.\n\n\nWe operate tirelessly around all time and world phases, with central offices in Spain, Europe.\n\n\nThe documentation that follows gives you access to our Crypto market data, Trading, and Custody products.\n\n# Data hierarchy\n\n\u003cfigure\u003e\n\n\u003cdiv class=\"data-hierarchy-wrapper\"\u003e\n  **Parent account / parent wallet**:\n  This account / wallet is manually created by Bit2Me and provided to you via API Keys.\n  This is your company’s master account and wallet. Parent accounts must be KYB’ed before operating.\n\n  \u003cdiv class=\"data-hierarchy-subaccount\"\u003e\n\n  **Sub Account / wallet**:\n  A parent account can create one **(1)** sub account / wallet on behalf of each end user.\n  You can generate as many end users as you want, but each can only operate on a single\n  sub account or wallet. *Sub Accounts must be KYC'ed before operating*.\n\n  \u003cdiv class=\"data-hierarchy-pocket\"\u003e\n\n  **Pocket**:\n  A wallet can own many pockets. *Each pocket can hold a specific type of currency*. For example: “BTC pocket”,\n  “ETH pocket”, “EUR pocket”… pockets are optional (you can operate at a wallet level).\n\n  \u003c/div\u003e\n\n  \u003c/div\u003e\n\n\u003c/div\u003e\n\n  \u003cfigcaption\u003e\u003cb\u003eFig. - Data hierarchy\u003c/b\u003e\u003c/figcaption\u003e\n\n\u003c/figure\u003e\n\n\n# Quickstart\n\n## Official Repositories\n\nAre you a coder? Check out these GitHub repositories to kickstart your journey with us!\n\n- [Bit2Me Broker](https://github.com/bit2me-dev/bit2me-api-node-tool)\n\n- [Bit2Me Pro](https://github.com/bit2me-devs/trading-spot-samples)\n\n## Postman\n\nBit2Me OpenAPI specification can be downloaded and imported in postman in order to generate collections.\u003cbr /\u003e\nOur OpenAPI specification can be downloaded from [main page](#crypto-page).\u003cbr /\u003e\nOpenAPI files can be imported in postman and generate collections from them following next steps:\n\n1. In postman left-hand sidebar, click **Import**.\n\n2. Choose the OpenAPI file to be imported.\n\n3. Configure the advanced options for the collection that will be generated.\n\n4. Click **Import**.\n\n# Logical steps to operate with API\n\n  1. [[Auth]](#section/Authentication) Obtain your API Keys for production environment from Bit2Me team.\n\n  2. [[Subaccount]](#tag/Account/operation/createSubaccount) Using your API Key, generate sub accounts for each individual user.\n\n  3. [[KYC]](#tag/KYC/operation/initKycVerificationTransactionV3) Perform the KYC to the individual user. If you\n    are a regulated entity and already perform an equivalent KYC on your side, our sales team will explain to you how to reuse it.\n\n  4. [[Funding]](#tag/Funding) your parent account with fiat money.\n\n      **Important notes**\n\n      * A minimum fiat balance is required to operate, as part of the initial set up there is a one time fiat transfer that must be\n        sent to the fiat account that Bit2Me will tell you during the onboarding process\n      * If you are a bank, the parent fiat account will be held in your own institution\n      * During the day to day operations, fiat money must be funded to the main account. You should\n        keep records of fiat money balances of each subaccount\n\n      4.1 [[Funding]](#tag/Funding/operation/getPocketReference) your account with EUR.\n\n      4.2 [[Funding]](#tag/Funding/operation/createOrderProforma) your account with BRL.\n\n      4.3 [Funding] your account with ARS. (Soon)\n\n      *If you're looking for USD, please get in touch with our sales team. Currently this is only available in Bit2Me Pro.\n\n  5. [[Funding]](#tag/Wallet/operation/findAddressesOrCreateOne) your account with crypto.\n\n  6. Obtain [[Market]](#tag/Market) information for price and rates.\n      * [Get a list of assets](#tag/Market/operation/currencyAssets)\n      * [Get ticker information for currency pair](#tag/Market/operation/currencyChart)\n\n  7. [[Wallet]](#tag/Wallet/operation/createTransaction) Create proforma transaction with the buy,\n    sell or exchange operation you want to execute.\n\n      After that:\n\n      7.1 [[Wallet]](#tag/Wallet/operation/performTransaction) Execute the proforma transaction you created earlier.\n\n  8. [[Trading]](#tag/Pro-(Trading-Spot)) Use Bit2Me Pro to do your high-frequency trading.\n      * [Deposit funds into your Bit2Me Pro account](/trading-spot-rest#tag/Funding/paths/~1v1~1trading~1wallet~1deposit/post)\n      * [Place an order](/trading-spot-rest#tag/Trading/paths/~1v1~1trading~1order/post)\n\n  9. [[Earn]](#tag/Earn) Deposit or withdraw crypto from earn protocols.\n      * [List supported assets](#tag/Earn/operation/getEarnAssetsV2)\n      * [Get assets annual percentage yields](#tag/Earn/operation/getApysEffectivesV2).\n      * [List subaccount earn wallets](#tag/Earn/operation/getEarnWallets).\n      * [Deposit/withdraw cryptos in earn](#tag/Earn/operation/createEarnMovement).\n\n  10. [[Transfers]](#tag/Transfers) Move money between users (peer to peer):\n      * [First create a transfer from the origin user](#tag/Transfers/operation/createOrder).\n      * [Then claim the transfer for the destination user](#tag/Transfers/operation/claimUserPendingOrders).\n\n  11. [[Withdraw]](#tag/Wallet/operation/createTransaction) your fiat.\n  12. [[Withdraw]](#tag/Wallet/operation/createTransaction) your crypto.\n\n  \u003cbr /\u003e\n\n  \u003e **`IMPORTANT: Logical steps are not examples, if you're looking for them, check the next section.`**\n\n# Use cases\n\n  The following are some common use cases that illustrate how our API can be leveraged:\n\n  1. **Perform KYC process**\n      * In order to perfom the KYC process first step is [complete subaccount data](#tag/Account/operation/updateAccount) following the examples in linked section.\n      Following information must be provided\n\n            {\n              \"person\": {\n                \"name\": \u003cString\u003e,\n                \"surname\": \u003cString\u003e,\n                \"birthDate\": \u003cDateISO8601\u003e,\n                \"nationalityCountryCode\": \u003cCountryISO3166-1Alpha2\u003e,\n              },\n              \"profile\": {\n                \"langCode\": \u003cLangISO639-1\u003e,\n                \"currencyCode\": \u003cCurrencyISO4217\u003e,\n                \"timeZone\": \u003cString\u003e\n              }\n            }\n\n      * Is mandatory to [add an address to the subaccount](#tag/Account/operation/createAddress) following the examples in linked section.\n\n      * [Init verification identity process](#tag/KYC/operation/initKycVerificationTransactionV3). This process has a predefined number of retries,\n      once the limit has been overcomed, contact with our support department in order to reset it. [Remaining retries can be checked](#tag/KYC/operation/canRetryIdentityVerification) following the examples in linked section.\n\n  2. **Enable main account google authenticator 2fa**\n      * [Retrieve 2fa user verification](#tag/Access/operation/getSfaTypeAndInitProcess) following the examples in linked section.\n      Sfatype is obtained in the response. A valid 2fa code is sent using indicated sfaType.\n\n      * [Start 2fa enablement process](#tag/Account/operation/settingsEnable2faStart) following the examples in linked section.\\\n      This endpoint returns a secret that has to be used to configure google authenticator and generate valid 2fa codes.\\\n      Following headers must be sent:\n        * x-totp: [[2fa-code obtained in previous step]]\n        * x-totp-type: [[sfaType obtained in previous response]]\n\n      * [End 2fa enablement process](#tag/Account/operation/settingsEnable2faEnd) following the examples in linked section.\n\n  3. **Enable subaccount google authenticator 2fa**\n      * [Start subaccount 2fa enablement process](#tag/Account/operation/initSubaccount2faProcess) following the examples in linked section.\\\n      This endpoint returns a secret that has to be used to configure google authenticator and generate valid 2fa codes.\n\n      * [End subaccount 2fa enablement process](#tag/Account/operation/endSubaccount2faProcess) following the examples in linked section.\n\n  4. **Deposit crypto in subaccount**\\\n    Subaccount users can receive crypto from a network address. Following steps should be done to achieve this action:\n      * [Create subaccount crypto pocket](#tag/Wallet/operation/createPocket).\\\n        If subaccount doesn't have a crypto pocket first step is to create one.\n\n      * [Get unique address for crypto pocket](#tag/Wallet/operation/getAddress).\\\n        Once subaccount crypto pocket is created, unique address can be generated.\n\n      * Receive cryptos in crypto pocket using generated address.\\\n      In order to transfer assets from another platform,\n      initiate a withdrawal from that account and paste this address into the destination field.\n      * Once the operation has been processed and the funds received in the pocket,\n      a notification of type \"wallet.trx.confirmed\" will be sent through [websockets](#section/Websockets).\n\n  5. **Fiat deposit**\n\n      * For EUR: [Check your bank accounts](#tag/Funding/operation/getPocketReference) and make a fiat transfer.\n      * For BRL: [Create a deposit proforma](#tag/Funding/operation/createOrderProforma).\n\n            {\n              \"amount\": \"10\",\n              \"description\": \"BRL deposit\",\n              \"currency\": \"BRL\",\n              \"feeType\": \"REA\",\n              \"orderType\": \"deposit\",\n              \"destination?\": {\n                \"type\": \"pocket\",\n                \"value\": \"\u003cUUID of an BRL pocket\u003e\"\n              },\n              \"method\": {\n                \"type\": \"hub-latam\",\n              }\n            }\n\n      5.1. **Receiving fiat deposits notifications**\n\n      When a fiat deposit is done (via bank transfer) a notification is generated via [websockets](#section/Websockets). Multiple notifications types can be generated related to fiat deposits:\n\n        * `wallet-transaction-v1`\n\n        * `teller-order-v1`\n\n        * `teller.deposit.transfer.success`\n\n        * `teller.deposit.transfer.error`\n\n      More information of this notifications can be found in websockets previously provided link.\n\n\n  6. **Calculate pocket balances**\n      * A pocket is needed. Pocket balance can be checked for fiat and crypto pockets.\\\n      Same operation can be used for subaccounts.\n\n      * [Get pocket balance](#tag/Wallet/operation/getPocketData) following examples in linked section\n\n  7. **Crypto buy operation**\\\n    To perform a buy operation follow next steps:\n      * [Generate a proforma](#tag/Wallet/operation/createTransaction) with following body\n\n            {\n              \"operation\": \"buy\",\n              \"pair\": \"BTC/EUR\",\n              \"amount\": \"100\",\n              \"currency\": \"EUR\"\n            }\n\n        With previous example, a proforma for an operation of buying 100 EUR of BTC is created. In the response, the **id** of the generated proforma is obtained.\n\n      * [Execute proforma confirmation](#tag/Wallet/operation/performTransaction) using previously obtained **id**\n\n  8. **Crypto sell operation**\\\n    To perform a sell operation follow next steps:\n      * [Generate a proforma](#tag/Wallet/operation/createTransaction) with following body\n\n            {\n              \"operation\": \"sell\",\n              \"pair\": \"BTC/EUR\",\n              \"amount\": \"0.001\",\n              \"currency\": \"BTC\"\n            }\n\n        With previous example, a proforma for an operation of selling 0.001 BTC is created. In the response, the **id** of the generated proforma is obtained.\n\n      * [Execute proforma confirmation](#tag/Wallet/operation/performTransaction) using previously obtained **id**\n\n  9. **Crypto swap operation**\\\n    To perform a swap operation follow next steps:\n      * [Generate a proforma](#tag/Wallet/operation/createTransaction) with following body\n\n            {\n              \"pocket\": \"\u003cUUID of a user crypto pocket\u003e\",\n              \"amount\": \"0.001\",\n              \"currency\": \"BTC\",\n              \"destination\": {\n                  \"pocket\": \"\u003cUUID of a user crypto pocket\u003e\"\n              },\n              \"type\": \"SEA\",\n              \"userCurrency\": \"EUR\"\n            }\n\n        With previous example, a proforma for an operation of swaping 0.001 BTC is created. In the response, the **id** of the generated proforma is obtained.\n\n      * [Execute proforma confirmation](#tag/Wallet/operation/performTransaction) using previously obtained **id**\n\n      **For more examples, go to [wallet create transaction](#tag/Wallet/operation/createTransaction) cURL section in requests samples side.**\n\n  10. **Deposit crypto in earn service**\n\n      * [Check available assets](#tag/Earn/operation/getEarnAssetsV2) in earn service\n\n      * [Create earn deposit](#tag/Earn/operation/createEarnMovement)\\\n      The **pocketId** must be a valid pocket identifier for the same currency you are depositing.\\\n      This operation can also be done for subaccounts as stated in linked section examples.\n\n  11. **Withdraw crypto from earn service**\n\n      * [List user earn wallets](#tag/Earn/operation/getEarnWallets) for detailed information\n      This endpoint can also be used for subaccounts as stated in linked sections example\n\n      * [Create earn withdraw](#tag/Earn/operation/createEarnMovement)\\\n      The **pocketId** must be a valid pocket identifier for the same currency you are withdrawing.\\\n      This operation can also be done for subaccounts as stated in linked section examples.\n\n  12. **Fiat withdraw (EUR)**\n      * An EUR pocket is needed\n\n      * [Create withdraw proforma](#tag/Wallet/operation/createTransaction) following examples in linked section.\n\n            {\n              \"pocket\": \"\u003cUUID of an EUR pocket\u003e\",\n              \"amount\": \"10\",\n              \"currency\": \"EUR\",\n              \"type\": \"SEA\",\n              \"concept\": \"\",\n              \"note\": \"\",\n              \"destination\": {\n                \"bankAccount\": {\n                    \"bankAccount\": \"\u003cIBAN bank account\u003e\",\n                    \"country\": \"ES\",\n                    \"receiverName\": \"Test\"\n                }\n              },\n              \"userCurrency\": \"EUR\"\n            }\n        These call will return an **id** field that has to be used in the next endpoint call.\n\n      * To confirm previous generated transaction, 2fa is requested\n\n      * [Execute withdraw order](#tag/Wallet/operation/performTransaction) following examples in linked section.\\\n        The response contains an **id** that identifies the executed withdraw order\n\n  13. **Fiat withdraw (BRL)**\u003cbr /\u003e\n    Fiat withdraws for Brazil are made using Pix instant payment platform. Following steps should be done to achieve this action:\n      * An EUR pocket is needed\n\n      * [Create pix withdraw proforma](#tag/Wallet/operation/createTransaction) following examples in linked section.\n\n            {\n              \"pocket\": \"\u003cUUID of an EUR pocket\u003e\",\n              \"amount\": \"10\",\n              \"currency\": \"EUR\",\n              \"type\": \"SEA\",\n              \"concept\": \"\",\n              \"note\": \"\",\n              \"destination\": {\n                \"bankAccount\": {\n                    \"bankAccount\": \"\u003cIBAN bank account\u003e\",\n                    \"country\": \"BR\",\n                    \"receiverName\": \"Test\",\n                    \"bankBranch\": \"02\",\n                    \"bankCode\": \"01\",\n                    \"bankName\": \"Bank test\",\n                    \"taxDocument\": \"\u003cCPF-CNPS\u003e\"\n                }\n              },\n              \"userCurrency\": \"EUR\"\n            }\n        These call will return an **id** field that has to be used in the next endpoint call.\n\n      * To confirm previous generated transaction, 2fa is requested\n\n      * [Execute pix withdraw order](#tag/Wallet/operation/performTransaction) following examples in linked section.\\\n        The response contains an **id** that identifies the executed withdraw order\n\n  14. **Withdraw crypto from subaccount**\\\n      Subaccount users can send crypto to a network address. Next steps should be followed to achieve this action:\n      * A subaccount crypto pocket with funds is needed.\n\n      * [Create a transaction](#tag/Wallet/operation/createTransaction) following the examples in linked section.\\\n      When generating transaction, following body example can be used:\n\n            {\n              \"pocket\": \"\u003cUUID of a user subaccount crypto pocket\u003e\",\n              \"currency\": \"ETH\",\n              \"amount\": \"0.005\",\n              \"type\": \"SEA\",\n              \"destination\": {\n                  \"address\": \"\u003cNetwork address\u003e\",\n                  \"network\": \"\u003cNetwork name\u003e\"\n              },\n              // If needed\n              // \"queryParams\" : \"\u003cMemo/Tag\u003e\"\n              \"userCurrency\": \"EUR\"\n            }\n\n      * To confirm previous generated transaction, first 2fa has to be requested\n\n      * [Confirm previous generated transaction](#tag/Wallet/operation/performTransaction) using next endpoint\n\n# Rate Limit\n\nTo ensure optimal performance and reliability of our API, we have implemented rate limits on the number of requests that can be made within a given timeframe. Below is a table detailing the allowed requests per minute (RPM) for different tiers:\n\n\u003cdiv\u003e\n  \u003ctable style=\"width: 100%; border-collapse: collapse;\"\u003e\n    \u003ctr style=\"background-color: silver; font-weight: bold;\"\u003e\n      \u003cth\u003eTier\u003c/td\u003e\n      \u003cth\u003eMax. RPM (request per minute)\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eStarter\u003c/td\u003e\n      \u003ctd\u003e600\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eMedium\u003c/td\u003e\n      \u003ctd\u003e800\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003ePro\u003c/td\u003e\n      \u003ctd\u003e1000\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/table\u003e\n\u003c/div\u003e\n\n\nTo request a new tier, [contact our support center](https://support.bit2me.com/en/support/home)\n\n\nAll endpoints of this API are designed to enforce strict usage policies to ensure fair access and optimal performance for all users. As a result, any request that exceeds the allowed rate limits, may trigger a HTTP response with two types of error:\n\n1. **`Code 429`**: The user has sent too many requests in a given timeframe.\n\n2. **`Code 418`**: The user has been banned from accessing the API.\n\n\n**Important note**: It is essential for users to adhere to the specified guidelines to avoid these error responses and maintain uninterrupted access to the API's functionalities, otherwise you'll be banned.\n\n\n# Status\n\n🔔 Stay updated with the latest platform updates and outages! Click the button below to **suscribe** to our service to receive all the news and announcements directly to your inbox.\n\n\n👉 \u003cbutton type=\"submit\" class=\"suscribe\" onclick=\"window.location.href='https://status.bit2me.com/'\" \u003e Suscribe \u003c/button\u003e 👈\n\n# WebSockets\n\nThis service has a websocket interface to communicate to the client all the notifications that happen in the platform.\nAfter the websocket connection you must send the JWT token or the API Key in order to authenticate the connection. If the authentication fails the websocket is closed immediately with code `4000`.\n\n\nWebSockets connection are limited by IP and also uses the same Rate Limiter as the HTTP calls:\n\n- If the maximum number of concurrent connections (50) from the same IP is exceeded a handshake error is returned with code `429`.\n\n- If the maximum number of messages sent (50 per second) from the same connection is exceeded, it will be closed with code `4001`.\n\n\nPlease also note, that you can **ONLY** receive events with a logged in account.\n\n## Reconnect policy\n\nWe recommend implementing an `on disconnect: reconnect` policy for WebSocket connections to our platform. This strategy ensures that, in the event of a connection interruption, the client will automatically attempt to reconnect, which enhances **resilience** and **user experience**.\n\n\nBy maintaining an active connection and efficiently reestablishing it, interruptions in communication are minimized, and a **continuous flow of data is guaranteed**, which is essential for real-time applications. This practice not only optimizes performance but also contributes to **greater stability** in interactions with our platform.\n\n## Code Snippets Examples\n\n**Example (browser-index.html)**\n\n```Javascript\n  \u003c!DOCTYPE HTML\u003e\n    \u003chtml\u003e\n        \u003chead\u003e\n            \u003cscript type = \"text/javascript\u003e\n\n            const ws = new WebSocket (`wss://${host}:${port}/`);\n\n            ws.addEventListener ('error', err =\u003e {\n              console.error ('websocket error:', err);\n            });\n\n            ws.addEventListener ('open', () =\u003e {\n              console.debug ('websocket connected');\n\n              // send the jwt token to authenticate the connection\n              ws.send (JSON.stringify ({ type: 'authenticate', payload: { token: jwt }}));\n\n              // or alternatively authenticate with apikey\n              ws.send (JSON.stringify ({ type: 'authenticate', payload: { apikey: [apikey] }}));\n            });\n\n            ws.addEventListener ('message', message =\u003e {\n              const msg = JSON.parse (message.data);\n              console.debug (`websocket message: type: ${msg.type}, id: ${msg.id}, time: ${msg.time}`);\n            });\n\n            ws.addEventListener ('close', evt =\u003e {\n              if (evt.code === 4000) {\n                console.log (`Error while authenticating: ${evt.code}/${evt.reason}`);\n              }\n              else if (evt.code === 4001) {\n                console.log (`Error rate limit: ${evt.code}/${evt.reason}`);\n              }\n              // handle reconnect logic\n            });\n\n            \u003c/script\u003e\n\n        \u003c/head\u003e\n        \u003cbody\u003e\n        ......\n        \u003c/body\u003e\n    \u003c/html\u003e\n```\n\n\u003cbr /\u003e\n**Example to receive tx notifications from BTC testnet crypto explorer (server- node.js)**\n\n```Javascript\n  const ws = new WebSocket (`wss://${host}:${port}/v1/explorer/BTCTEST`);\n\n  ws.addEventListener ('error', err =\u003e {\n    console.error ('websocket error:', err);\n  });\n\n  ws.addEventListener ('open', () =\u003e {\n    console.debug ('websocket connected');\n\n    // subscribe to 'inv' room\n    ws.send (JSON.stringify ([ 'subscribe', 'inv' ]));\n  });\n\n  ws.addEventListener ('message', message =\u003e {\n    const msg = JSON.parse (message);\n\n    // we want just transactions\n    if (msg[0] === 'tx') {\n      console.debug ('websocket message:', msg[1]);\n      // ...\n    }\n  });\n\n  ws.addEventListener ('close', evt =\u003e {\n    if (evt.code === 4001) {\n      console.log (`Error rate limit: ${evt.code}/${evt.reason}`);\n    }\n    else if (evt.code === 4002) {\n      console.log (`Wrong crypto explorer: ${evt.code}/${evt.reason}`);\n    }\n    // handle reconnect logic\n  });\n```\n\n## WebSockets received\n\nAll WebSockets recieved have the same structure:\n\n\n`{ channel: string, id: string, time: number, type: string, payload: object }`\n\n\nDepends on the type, the payload is different:\n\n\n\u003cdiv\u003e\n  \u003ctable style=\"width: 100%; border-collapse: collapse;\"\u003e\n    \u003ctr style=\"background-color: silver; font-weight: bold;\"\u003e\n      \u003ctd\u003eType\u003c/td\u003e\n      \u003ctd\u003ePayload\u003c/td\u003e\n      \u003ctd\u003eDescription\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd colspan=\"3\"\u003e\u0026nbsp;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003efile.download.error\u003c/td\u003e\n        \u003ctd\u003e{ message }\u003c/td\u003e\n        \u003ctd\u003eError downloading a file.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003efile.download\u003c/td\u003e\n        \u003ctd\u003e{ path }\u003c/td\u003e\n        \u003ctd\u003eReceiving a file.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eaccouting.entries.success\u003c/td\u003e\n        \u003ctd\u003e{ }\u003c/td\u003e\n        \u003ctd\u003eAccounting a document generation.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eaccounting.entries.error\u003c/td\u003e\n        \u003ctd\u003e{ error: { date, message } }\u003c/td\u003e\n        \u003ctd\u003eError generating accounting document.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd colspan=\"3\"\u003e\u0026nbsp;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eaffiliate.activity\u003c/td\u003e\n        \u003ctd\u003e{ action, serial, earnings, points } [ action: 'newEarnings' ]\u003cbr /\u003e{ action, earnings } [ action: 'adminUpdate' ]\u003cbr /\u003e{ action } [ action: 'payoutRejected' ]\u003c/td\u003e\n        \u003ctd\u003eAn affiliate has generated an activity.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eaffiliate.invoice\u003c/td\u003e\n        \u003ctd\u003e{ email, langCode, name, surname, action, pocketId, pocketName, earnings }\u003c/td\u003e\n        \u003ctd\u003eAffiliate benefits have been processed and invoice generated.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd colspan=\"3\"\u003e\u0026nbsp;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ecurrency.rates\u003c/td\u003e\n        \u003ctd\u003e{ type, rates } [ type: 'fiat' || 'crypto' ]\u003c/td\u003e\n        \u003ctd\u003eReceipt of currency price changes in case they have changed.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd colspan=\"3\"\u003e\u0026nbsp;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003einstant.process.postponed.orders.finished\u003c/td\u003e\n        \u003ctd\u003e{ }\u003c/td\u003e\n        \u003ctd\u003eNotification when orders postponed due to exchange failure have been reprocessed correctly.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd colspan=\"3\"\u003e\u0026nbsp;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003esocial.payment.expiration\u003c/td\u003e\n        \u003ctd\u003e{ type, email, langCode, name, surname, amount, currency }\u003c/td\u003e\n        \u003ctd\u003ePending payment expired.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003esocial.payment.success\u003c/td\u003e\n        \u003ctd\u003e{ pocketId, amount, currency }\u003c/td\u003e\n        \u003ctd\u003eYou have received a payment.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003esocial.payment.pending\u003c/td\u003e\n        \u003ctd\u003e{ name, surname, amount, currency, expiryDate }\u003c/td\u003e\n        \u003ctd\u003ePending payment.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd colspan=\"3\"\u003e\u0026nbsp;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eteller.new.card.success\u003c/td\u003e\n        \u003ctd\u003e{ cardId, alias }\u003c/td\u003e\n        \u003ctd\u003eCredit card added successfully.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eteller.new.card.error\u003c/td\u003e\n        \u003ctd\u003e{ code, message }\u003c/td\u003e\n        \u003ctd\u003eFailed to add new credit card.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eteller.purchase.card.success\u003c/td\u003e\n        \u003ctd\u003e{ pocketId, amount, currency, transactionId }\u003c/td\u003e\n        \u003ctd\u003ePurchase made correctly by credit card.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eteller-order-v1\u003c/td\u003e\n        \u003ctd\u003e{ orderId, status, type, error }\u003c/td\u003e\n        \u003ctd\u003eTeller order performed\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n          \u003cdiv\u003e\n            \u003cspan style=\"color: red\"\u003e[DEPRECATED]\u003c/span\u003e\n            use \u003cb\u003eteller-order-v1\u003c/b\u003e\n          \u003c/div\u003e\n          \u003cdiv\u003e\n            \u003cdel\u003eteller.purchase.card.error\u003c/del\u003e\n          \u003c/div\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e{ code, message }\u003c/td\u003e\n        \u003ctd\u003eFailed to buy with a credit card.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n          \u003cdiv\u003e\n            \u003cspan style=\"color: red\"\u003e[DEPRECATED]\u003c/span\u003e\n             use \u003cb\u003ewallet-transaction-v1\u003c/b\u003e\n          \u003c/div\u003e\n          \u003cdiv\u003e\n            \u003cdel\u003eteller.deposit.card.success\u003c/del\u003e\n          \u003c/div\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e{ pocketId, amount, currency, transactionId }\u003c/td\u003e\n        \u003ctd\u003eCredit card deposit made correctly.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n          \u003cdiv\u003e\n            \u003cspan style=\"color: red\"\u003e[DEPRECATED]\u003c/span\u003e\n             use \u003cb\u003eteller-order-v1\u003c/b\u003e\n          \u003c/div\u003e\n          \u003cdiv\u003e\n            \u003cdel\u003eteller.deposit.card.error\u003c/del\u003e\n          \u003c/div\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e{ code, message }\u003c/td\u003e\n        \u003ctd\u003eFailed to deposit with credit card.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eteller.deposit.transfer.success\u003c/td\u003e\n        \u003ctd\u003e{ pocketId, amount, currency, transactionId }\u003c/td\u003e\n        \u003ctd\u003eDeposit by bank transfer received.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eteller.deposit.transfer.error\u003c/td\u003e\n        \u003ctd\u003e{ code, message }\u003c/td\u003e\n        \u003ctd\u003eError when depositing bank transfer.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd colspan=\"3\"\u003e\u0026nbsp;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n          \u003cdiv\u003e\n            \u003cspan style=\"color: red\"\u003e[DEPRECATED]\u003c/span\u003e\n            use \u003cb\u003eteller-order-v1\u003c/b\u003e\n          \u003c/div\u003e\n          \u003cdiv\u003e\n            \u003cdel\u003enotice.unverified.card\u003c/del\u003e\n          \u003c/div\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e{ email, langCode, last_4 }\u003c/td\u003e\n        \u003ctd\u003eUser performs an operation with a card that is not verified.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd colspan=\"3\"\u003e\u0026nbsp;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n          \u003cdiv\u003e\n            \u003cspan style=\"color: red\"\u003e[DEPRECATED]\u003c/span\u003e\n            use \u003cb\u003eteller-order-v1\u003c/b\u003e\n          \u003c/div\u003e\n          \u003cdiv\u003e\n            \u003cdel\u003elaunchpad.purchase.card.error\u003c/del\u003e\n          \u003c/div\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e{ code, message }\u003c/td\u003e\n        \u003ctd\u003eUser tries to make a purchase through Launchpad using credit card as payment method and some kind of error occurs.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd colspan=\"3\"\u003e\u0026nbsp;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eidentity.pending\u003c/td\u003e\n        \u003ctd\u003e{ langCode, email }\u003c/td\u003e\n        \u003ctd\u003ePending Identity.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eidentity.validated\u003c/td\u003e\n        \u003ctd\u003e{ langCode, email }\u003c/td\u003e\n        \u003ctd\u003eVerified identity.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eidentity.rejected\u003c/td\u003e\n        \u003ctd\u003e{ langCode, email }\u003c/td\u003e\n        \u003ctd\u003eIdentity rejected.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eidentity.nodata\u003c/td\u003e\n        \u003ctd\u003e{ langCode, email }\u003c/td\u003e\n        \u003ctd\u003eIdentity without data.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eidentity.image.uploaded\u003c/td\u003e\n        \u003ctd\u003e{ image, dataUrl } [ image: 'document' || 'selfie' ]\u003c/td\u003e\n        \u003ctd\u003eAn image of the verification process via smartphone has been uploaded successfully.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eidentity.image.error\u003c/td\u003e\n        \u003ctd\u003e{ image, dataUrl } [ image: 'document' || 'selfie' ]\u003c/td\u003e\n        \u003ctd\u003eError uploading image verification process using smartphone.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eemail.confirm.done\u003c/td\u003e\n        \u003ctd\u003e{ email }\u003c/td\u003e\n        \u003ctd\u003eEmail confirmed correctly.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd colspan=\"3\"\u003e\u0026nbsp;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eidentity.enhanced.measures.required\u003c/td\u003e\n        \u003ctd\u003e{ langCode, email }\u003c/td\u003e\n        \u003ctd\u003eUser receives a message via websocket indicating that his identity is in Pending status.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd colspan=\"3\"\u003e\u0026nbsp;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ewallet.promo.referral.error\u003c/td\u003e\n        \u003ctd\u003e{ pocketId, amount, currency }\u003c/td\u003e\n        \u003ctd\u003eAn error has occurred when receiving the 5€ promo of a new referral when buying 100€.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ewallet.promo.referral.success\u003c/td\u003e\n        \u003ctd\u003e{ pocketId, amount, currency }\u003c/td\u003e\n        \u003ctd\u003eFor being affiliated and having made an operation equal to or greater than 100€ you have received {{amount}} FREE.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ewallet-transaction-v1\u003c/td\u003e\n        \u003ctd\u003e{ userId, pocketId, amount, currency, transactionId, status, tellerId }\u003c/td\u003e\n        \u003ctd\u003eWallet transaction performed\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ewallet.trx.received\u003c/td\u003e\n        \u003ctd\u003e{ pocketId, amount, currency, transactionId, langCode, name, surname?, pocketName, email }\u003c/td\u003e\n        \u003ctd\u003eTransaction received from the blockchain successfully.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ewallet.trx.confirmed\u003c/td\u003e\n        \u003ctd\u003e{ pocketId, amount, currency, transactionId }\u003c/td\u003e\n        \u003ctd\u003eTransaction confirmed.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ewallet.trx.reimbursement\u003c/td\u003e\n        \u003ctd\u003e{ pocketId, amount, currency, bankAccount, transactionId, tellerOrderId }\u003c/td\u003e\n        \u003ctd\u003eTransaction refunded.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ewallet.trx.cancellation\u003c/td\u003e\n        \u003ctd\u003e{ pocketId, amount, currency, bankAccount, transactionId, tellerOrderId }\u003c/td\u003e\n        \u003ctd\u003eTransaction canceled.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd colspan=\"3\"\u003e\u0026nbsp;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003elaunchpad.purchase.card.success\u003c/td\u003e\n        \u003ctd\u003e{ transactionId }\u003c/td\u003e\n        \u003ctd\u003eUser makes a successful purchase using credit card as a payment method.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003elaunchpad.purchase.pocket.success\u003c/td\u003e\n        \u003ctd\u003e{ transactionId }\u003c/td\u003e\n        \u003ctd\u003eUser makes a successful purchase using his EUR wallet as a payment method.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003elaunchpad.purchase.pocket.error\u003c/td\u003e\n        \u003ctd\u003e{ transactionId }\u003c/td\u003e\n        \u003ctd\u003eUser tries to make a purchase using his EUR wallet as a payment method but the operation fails.\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/table\u003e\n\u003c/div\u003e\n\n\n# Authentication\n\n## ApiKeyAuth\n\nThe Bit2Me Crypto API service requires an api key to access private endpoints. 🔑 To get your API Keys,\nplease get in touch with our sales team. Our knowledge base contains a detailed guide on how to work with API keys.\n\n\n⚠️ Never share an API key, if you suspect that an API key was compromised revoke it immediately.\n\n\nWhen generating an API key, you can ask us to customize it using the following scopes for the keys:\n\n* Read - grants access to all api endpoints, except for creating or canceling orders and transfers.\n\n\n* Trade - allows creation or cancellation of orders.\n\n\n* Withdraw - allows withdrawals (these withdrawals bypass two factor authentication).\n\n\nYou may optionally add an IP restriction. Any request using that API key is rejected, unless the source IP of the\nrequest is one of the trusted IPs.\n\n\n⚠️ Always select the minimal required scope for an api key. We recommend to set one or more trusted IPs to further\nharden API keys with scope Trade or Withdraw.\n\n\nMake sure that your client validates the server certificate and aborts if validation fails.\n\nFor accessing the API a valid API-Key must be passed in the header.\n\n\u003cdiv class=\"box-info-wrapper\"\u003e\n  \u003cdiv class=\"box-info-title\"\u003e\n    \u003ci class=\"material-symbols-outlined\"\u003einfo\u003c/i\u003e\n    \u003ch6\u003eTo operate on behalf of a subaccount.\u003c/h6\u003e\n  \u003c/div\u003e\n\n  It is necessary to add the token that identifies it. To do this the following\n  key/value must be sent on header:\n\n    X-SUBACCOUNT-ID: \u003csubaccount id\u003e\n\n\u003c/div\u003e\n\n\nThe following key/value must be sent on header:\n\n    X-API-KEY: yourGeneratedApiKey\n\n\nNonce header is also required to be sent. The nonce value corresponds to the current value of the unix timestamp in UTC and has a valid time window of 5 seconds.\n\n  ```\n  x-nonce: 1687155308\n  ```\n\nIf request needs to be signed you have to include following header:\n\n  ```\n  api-signature: \u003csignature\u003e\n  ```\n\nSignature must be generated using the nonce, the request URL and the body. An example in javascript to `GET /v1/trading/wallet/balance` is shown below:\n\n  ``` javascript\n  const axios = require('axios');\n  const crypto = require('crypto');\n\n  const API_KEY = 'YOUR API KEY;\n  const SECRET = 'YOUR SECRET;\n\n  const NONCE = Date.now(); // MUST be UTC time zone\n  const PATH = '/v1/trading/wallet/balance';\n  const SERVER = 'https://gateway.bit2me.com';\n\n  const getAuthHeaders = (nonce, path, body) =\u003e {\n    const messageToSign = getClientMessageToSign(nonce, path, body);\n    const signature = getMessageSignature(messageToSign, SECRET);\n\n    return {\n      headers: {\n        'x-api-key': API_KEY,\n        'api-signature': signature,\n        'x-nonce': nonce\n      }\n    };\n  };\n\n  const getClientMessageToSign = (nonce, url, body) =\u003e {\n    const hasBody = !!body;\n\n    return hasBody\n      ? `${nonce}:${url}:${JSON.stringify(body)}`\n      : `${nonce}:${url}`;\n  };\n\n  const getMessageSignature = (message, secret) =\u003e {\n    const hash = crypto.createHash('sha256');\n    const hmac = crypto.createHmac('sha512', secret);\n    const hashDigest = hash.update(message).digest('binary');\n    const hmacDigest = hmac.update(hashDigest, 'binary').digest('base64');\n\n    return hmacDigest;\n  };\n\n  const config = getAuthHeaders(NONCE, PATH, undefined);\n  const response = await axios.get(`${SERVER}${PATH}`, config);\n  console.log(response.data);\n\n  ```\n\n  **Important:** The body used to generate the signature must be the request body string. In javascript, it can be obtained with `JSON.stringify(body)`.\n\n  ``` javascript\n  const nonce = 1687155308;\n  const url = '/v1/trading/order';\n  const body = {\n    side: \"sell\",\n    symbol: \"B2M/EUR\",\n    price: \"0.09999\",\n    amount: \"5001.00000000\",\n    orderType: \"limit\"\n  };\n\n  const bodyString = JSON.stringify(body);\n  const messageToSign = `${nonce}:${url}:${bodyString}`;\n  const signature = getMessageSignature(messageToSign, SECRET);\n\n  const response = await axios.post(`${SERVER}${url}`, body, {\n    headers: {\n      'Content-Type': 'application/json',\n      'x-api-key': API_KEY,\n      'api-signature': signature,\n      'x-nonce': nonce\n    }\n  });\n  ```\n\n## TOTP\n\nThere are some operations that require 2FA authentication. Following headers must be included in this cases:\n\n* Header x-totp - contains 2FA code\n\n\n* Header x-totp-type - contains the type of how the 2FA code was received (Type: ['gauth', 'sms', 'email'])\n\n\n⚠️ For subaccount operations the totp-type always will be 'gauth'","name":"Crypto Suite"}],"x-tagGroups":[{"name":"Basic Info","tags":["Crypto Suite"]},{"name":"Crypto Suite Endpoints","tags":["Account","Accounting","Affiliates","Auth","Blockchain Manager","Brokerage","Captcha","Card","Card Authorizator","Card Loyalty","Collection Orders","Commerce","Compliance","Configuration","Crypto Credentials","Currency","Currency Analytics","Currency Collections","Currency Favorites","Earn","External Onboarding","Instant","Junior","Launchpad","Loan","Misc","Notification","Portfolio","Portfolio Analytics","Price Alert Scheduler","Price Orders","Price Watchdog","Promotion","Recurring Orders","Pay","Redeem Token","Space Center","Stocks","Support","Taxes","Teller","Terms and Conditions","Travel Rule","Trading","Translations","UX","Verifier","Wallet"]},{"name":"Deprecated","tags":["Account Deprecated Methods","Auth Deprecated Methods","Currency Deprecated Methods","Earn Deprecated Methods","Verifier Deprecated Methods"]}]}