SX Customers

Customer Management

Create, read, update, and delete your customer account, and issue or revoke the API credentials it authenticates with.

Manage your customer account: create it, read and update its profile, delete it, and issue or revoke the API credentials your backend uses to call the rest of the platform. The customer is the tenant your end users live under—create it first, then issue a credential before you create users or open wallets.

Authentication: every endpoint on this page takes your dashboard session token as a Bearer token. The session must own the {customer_id} in the path; any other id answers 404 CUSTOMER_NOT_FOUND, so ids can't be probed across accounts. Deleting the customer and issuing or revoking credentials also require the account holder's session: a team member who shares the account gets 403 ACCOUNT_OWNER_REQUIRED, and nothing changes.

Authorization: Bearer YOUR_SESSION_TOKEN

Responses use the standard envelope and error format. POST and PATCH accept an optional x-idempotency-key header, except where noted.

The customer resource

id and customer_id carry the same platform customer id. status is always VERIFIED: a customer reaches this API only once it's verified. Unknown profile values come back as null, never as placeholders, and every business key is always present. Dates are UTC without milliseconds; see Timestamps.


Create Customer

POSThttps://api.sandbox.sovera.io/sovx/v1/customers

Register your customer account. Pass the customer_id issued at registration, a contact email, and the legal entity name. The service checks the session owns that id, pulls the business profile, and stores the record. The response is the customer resource with a location header pointing at it.

Request Body

FieldTypeRequiredDescription
customer_idstringYesPlatform customer id issued at registration (max 48).
emailstringYesPrimary contact email (max 255).
entity_namestringYesLegal name of the business entity (max 255).
{
  "customer_id": "corp-redundant-firewall",
  "email": "[email protected]",
  "entity_name": "Hedge Fund e-commerce"
}

Success Response (201 Created):

{
  "success": true,
  "data": {
    "id": "corp-redundant-firewall",
    "object": "customer",
    "customer_id": "corp-redundant-firewall",
    "account_type": "CORPORATION",
    "account_role": "CLIENT",
    "account_purpose": null,
    "first_name": "Hedge",
    "last_name": "Fund e-commerce",
    "email": "[email protected]",
    "phone_country_code": "US",
    "phone_number": null,
    "business": {
      "entity_name": "Hedge Fund e-commerce",
      "incorporation_country": "VC",
      "incorporation_state": "Kingstown",
      "incorporation_date": "2012-11-15",
      "organization_type": "LLC",
      "business_type": "Fund Administrator",
      "registration_number": "3201LLC2023",
      "description": "crypto fund",
      "is_accredited_investor": true,
      "is_non_agent_intermediary": true,
      "principal_place_country": "US",
      "principal_place_state": "CA",
      "principal_place_address": "1234 Flower Street",
      "principal_place_city": "Los Angeles",
      "principal_place_postal_code": "90403"
    },
    "status": "VERIFIED",
    "created_at": "2026-10-12T14:03:21Z",
    "updated_at": "2026-10-12T14:03:21Z",
    "created_by": "1d8cb40d-8740-5a6b-94c3-7406e08ab4fd",
    "updated_by": "1d8cb40d-8740-5a6b-94c3-7406e08ab4fd"
  },
  "meta": {
    "timestamp": "2026-10-12T14:03:21Z",
    "version": "v1",
    "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
curl -X POST "https://api.sandbox.sovera.io/sovx/v1/customers" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_SESSION_TOKEN" \
  -H "x-idempotency-key: 9a7c3e1f-5b2d-4c8e-a6f0-1d3b5e7f9a2c" \
  -d '{
    "customer_id": "corp-redundant-firewall",
    "email": "[email protected]",
    "entity_name": "Hedge Fund e-commerce"
  }'

Customer Fields

FieldTypeDescription
idstringPlatform customer id (same value as customer_id).
objectstringAlways customer.
customer_idstringPlatform customer id.
account_typestringINDIVIDUAL or CORPORATION. Read-only.
account_rolestringCLIENT or PARTNER. Read-only.
account_purposestring | nullPrimary use of the account.
first_name / last_namestring | nullAccount holder name.
emailstringPrimary contact email. Read-only after creation.
phone_country_codestring | nullISO 3166-1 alpha-2 country of the phone number.
phone_numberstring | nullContact phone number.
businessobjectBusiness profile. Every key is present; unknown values are null. Booleans are is_accredited_investor and is_non_agent_intermediary.
statusstringAlways VERIFIED.
created_at / updated_atstringUTC timestamps.
created_by / updated_bystring | nullActor that created or last changed the record.

Errors: 401 UNAUTHORIZED missing or invalid session · 404 CUSTOMER_NOT_FOUND the session doesn't own this customer_id · 409 CUSTOMER_ALREADY_EXISTS (source.pointer: /customer_id) · 422 VALIDATION_ERROR invalid field, one error per field with source.pointer.


Get Customer

GEThttps://api.sandbox.sovera.io/sovx/v1/customers/:customer_id

Return your customer resource. A deleted customer answers 404 CUSTOMER_NOT_FOUND.

GET https://api.sandbox.sovera.io/sovx/v1/customers/corp-redundant-firewall

Success Response (200 OK):

{
  "success": true,
  "data": {
    "id": "corp-redundant-firewall",
    "object": "customer",
    "customer_id": "corp-redundant-firewall",
    "account_type": "CORPORATION",
    "account_role": "CLIENT",
    "account_purpose": "Arbitrage Trading",
    "first_name": "Hedge",
    "last_name": "Fund e-commerce",
    "email": "[email protected]",
    "phone_country_code": "US",
    "phone_number": "408-721-7741",
    "business": {
      "entity_name": "Hedge Fund e-commerce",
      "incorporation_country": "VC",
      "incorporation_state": "Kingstown",
      "incorporation_date": "2012-11-15",
      "organization_type": "LLC",
      "business_type": "Fund Administrator",
      "registration_number": "3201LLC2023",
      "description": "crypto fund",
      "is_accredited_investor": true,
      "is_non_agent_intermediary": true,
      "principal_place_country": "US",
      "principal_place_state": "CA",
      "principal_place_address": "1234 Flower Street",
      "principal_place_city": "Los Angeles",
      "principal_place_postal_code": "90403"
    },
    "status": "VERIFIED",
    "created_at": "2026-10-12T14:03:21Z",
    "updated_at": "2026-10-12T15:10:04Z",
    "created_by": "1d8cb40d-8740-5a6b-94c3-7406e08ab4fd",
    "updated_by": "1d8cb40d-8740-5a6b-94c3-7406e08ab4fd"
  },
  "meta": {
    "timestamp": "2026-10-12T15:10:09Z",
    "version": "v1",
    "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
curl -X GET "https://api.sandbox.sovera.io/sovx/v1/customers/corp-redundant-firewall" \
  -H "Authorization: Bearer YOUR_SESSION_TOKEN"

Errors: 401 UNAUTHORIZED missing or invalid session · 404 CUSTOMER_NOT_FOUND not owned by the session, or deleted.


Update Customer

PATCHhttps://api.sandbox.sovera.io/sovx/v1/customers/:customer_id

Change profile fields. Send only what changes: a field you send replaces the stored value, null clears it, and a field you leave out stays as it is. business merges key by key the same way, so updating one business field never wipes the others. The response is the full customer resource.

account_type, account_role, email, and status aren't writable. Sending any of them, or any unknown field, answers 422 VALIDATION_ERROR with a source.pointer for each one. PUT /v1/customers/{customer_id} still works as a deprecated alias with the same merge behavior.

Request Body

FieldTypeRequiredDescription
account_purposestring | nullNoPrimary use of the account (max 200).
first_namestring | nullNoAccount holder first name (max 100).
last_namestring | nullNoAccount holder last name (max 100).
phone_country_codestring | nullNoISO 3166-1 alpha-2 code, e.g. US.
phone_numberstring | nullNoContact phone number (max 20).
businessobjectNoBusiness fields to merge (below).

business object

Every field is optional and nullable.

FieldTypeDescription
entity_namestringLegal name (max 255).
incorporation_countrystringISO 3166-1 alpha-2.
incorporation_statestringState or province of incorporation.
incorporation_datestringYYYY-MM-DD.
organization_typestringLegal structure, e.g. LLC.
business_typestringIndustry or activity.
registration_numberstringRegistration or license number.
descriptionstringShort description of the business.
is_accredited_investorbooleanAccredited investor flag. accredited_investor is a deprecated alias.
is_non_agent_intermediarybooleanNon-agent intermediary flag. non_agent_intermediary is a deprecated alias.
principal_place_countrystringISO 3166-1 alpha-2.
principal_place_statestringState or province.
principal_place_addressstringStreet address.
principal_place_citystringCity.
principal_place_postal_codestringPostal code.
{
  "account_purpose": "Arbitrage Trading",
  "phone_number": "408-721-7741",
  "business": {
    "incorporation_country": "US",
    "organization_type": "LLC"
  }
}

Success Response (200 OK):

{
  "success": true,
  "data": {
    "id": "corp-redundant-firewall",
    "object": "customer",
    "customer_id": "corp-redundant-firewall",
    "account_type": "CORPORATION",
    "account_role": "CLIENT",
    "account_purpose": "Arbitrage Trading",
    "first_name": "Hedge",
    "last_name": "Fund e-commerce",
    "email": "[email protected]",
    "phone_country_code": "US",
    "phone_number": "408-721-7741",
    "business": {
      "entity_name": "Hedge Fund e-commerce",
      "incorporation_country": "US",
      "incorporation_state": "Kingstown",
      "incorporation_date": "2012-11-15",
      "organization_type": "LLC",
      "business_type": "Fund Administrator",
      "registration_number": "3201LLC2023",
      "description": "crypto fund",
      "is_accredited_investor": true,
      "is_non_agent_intermediary": true,
      "principal_place_country": "US",
      "principal_place_state": "CA",
      "principal_place_address": "1234 Flower Street",
      "principal_place_city": "Los Angeles",
      "principal_place_postal_code": "90403"
    },
    "status": "VERIFIED",
    "created_at": "2026-10-12T14:03:21Z",
    "updated_at": "2026-10-12T15:10:04Z",
    "created_by": "1d8cb40d-8740-5a6b-94c3-7406e08ab4fd",
    "updated_by": "1d8cb40d-8740-5a6b-94c3-7406e08ab4fd"
  },
  "meta": {
    "timestamp": "2026-10-12T15:10:04Z",
    "version": "v1",
    "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
curl -X PATCH "https://api.sandbox.sovera.io/sovx/v1/customers/corp-redundant-firewall" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_SESSION_TOKEN" \
  -d '{
    "account_purpose": "Arbitrage Trading",
    "phone_number": "408-721-7741",
    "business": { "incorporation_country": "US", "organization_type": "LLC" }
  }'

Errors: 401 UNAUTHORIZED missing or invalid session · 404 CUSTOMER_NOT_FOUND not owned by the session, or deleted · 422 VALIDATION_ERROR invalid, read-only, or unknown field.


Delete Customer

DELETEhttps://api.sandbox.sovera.io/sovx/v1/customers/:customer_id

Soft-delete your customer account. Every credential is revoked and the email poller is disabled in the same call. All user tokens issued under your credentials are revoked as well. Afterwards the customer and its sub-resources (credentials, email poller, webhook, vault reads) answer 404 CUSTOMER_NOT_FOUND. Account holder only.

DELETE https://api.sandbox.sovera.io/sovx/v1/customers/corp-redundant-firewall

Success Response (204 No Content)—empty body.

curl -X DELETE "https://api.sandbox.sovera.io/sovx/v1/customers/corp-redundant-firewall" \
  -H "Authorization: Bearer YOUR_SESSION_TOKEN"

Errors: 401 UNAUTHORIZED missing or invalid session · 403 ACCOUNT_OWNER_REQUIRED the session belongs to a team member, not the account holder · 404 CUSTOMER_NOT_FOUND not owned by the session, or already deleted.


Generate Credentials

POSThttps://api.sandbox.sovera.io/sovx/v1/customers/:customer_id/credentials

Issue an API credential for your backend. The response is the credential resource with customer_secret—the key you send as x-api-key. It's shown only on this response: store it right away. Send no body. Account holder only.

This endpoint ignores x-idempotency-key and never replays a response, so the secret is never cached. Every successful call issues a new credential.

POST https://api.sandbox.sovera.io/sovx/v1/customers/corp-redundant-firewall/credentials

Success Response (201 Created):

{
  "success": true,
  "data": {
    "id": "a3f1c2d4-5e6f-4081-92a3-b4c5d6e7f809",
    "object": "credential",
    "customer_id": "corp-redundant-firewall",
    "customer_secret": "uiFkvaYbt1YfBO2NiXyi1txbdysIxa8H",
    "customer_secret_prefix": "uiFkvaYb",
    "is_owner": true,
    "is_active": true,
    "user_email": "[email protected]",
    "user_name": "Hedge Fund e-commerce",
    "expires_at": null,
    "last_used_at": null,
    "created_at": "2026-10-12T14:05:00Z",
    "updated_at": "2026-10-12T14:05:00Z",
    "created_by": "1d8cb40d-8740-5a6b-94c3-7406e08ab4fd",
    "updated_by": "1d8cb40d-8740-5a6b-94c3-7406e08ab4fd"
  },
  "meta": {
    "timestamp": "2026-10-12T14:05:00Z",
    "version": "v1",
    "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
curl -X POST "https://api.sandbox.sovera.io/sovx/v1/customers/corp-redundant-firewall/credentials" \
  -H "Authorization: Bearer YOUR_SESSION_TOKEN"

Credential Fields

FieldTypeDescription
idstringCredential id (UUID).
credential_idstringSame value as id. Returned by the list only.
objectstringAlways credential.
customer_idstringOwning customer.
customer_secretstringThe API key. Only on the create response.
customer_secret_prefixstring | nullFirst 8 characters of the key, to tell credentials apart.
is_ownerbooleanWhether this is an owner credential.
is_activebooleanWhether the credential authenticates requests.
user_email / user_namestring | nullContact the credential was issued for.
expires_atstring | nullAlways null: credentials don't expire today.
last_used_atstring | nullLast time the credential authenticated a request, UTC; null until its first use. Updated at most once a minute.
created_at / updated_atstringUTC timestamps.
created_by / updated_bystring | nullActor that created or last changed the credential.

Errors: 401 UNAUTHORIZED missing or invalid session · 403 ACCOUNT_OWNER_REQUIRED the session belongs to a team member, not the account holder · 404 CUSTOMER_NOT_FOUND not owned by the session, or deleted · 502 CREDENTIAL_ISSUANCE_FAILED the key couldn't be issued; try again later.


List Credentials

GEThttps://api.sandbox.sovera.io/sovx/v1/customers/:customer_id/credentials

List your active credentials, newest first, with cursor pagination. The secret is never returned here—only its prefix.

Query Parameters

ParameterTypeRequiredDescription
filter[limit]integerNoItems per page (default 25, max 100).
cursorstringNoOpaque cursor from meta.pagination.navigation.
filter[order]stringNocreated_at or updated_at, ASC or DESC (default created_at DESC).
filter[where][is_owner][eq]stringNotrue or false.
filter[where][created_at][gte|lte|between]stringNoUTC date-time ending in Z.
GET https://api.sandbox.sovera.io/sovx/v1/customers/corp-redundant-firewall/credentials?filter[limit]=25

Success Response (200 OK):

{
  "success": true,
  "data": [
    {
      "id": "a3f1c2d4-5e6f-4081-92a3-b4c5d6e7f809",
      "credential_id": "a3f1c2d4-5e6f-4081-92a3-b4c5d6e7f809",
      "object": "credential",
      "customer_id": "corp-redundant-firewall",
      "customer_secret_prefix": "uiFkvaYb",
      "is_owner": true,
      "is_active": true,
      "user_email": "[email protected]",
      "user_name": "Hedge Fund e-commerce",
      "expires_at": null,
      "last_used_at": "2026-10-12T15:42:00Z",
      "created_at": "2026-10-12T14:05:00Z",
      "updated_at": "2026-10-12T14:05:00Z",
      "created_by": "1d8cb40d-8740-5a6b-94c3-7406e08ab4fd",
      "updated_by": "1d8cb40d-8740-5a6b-94c3-7406e08ab4fd"
    }
  ],
  "meta": {
    "timestamp": "2026-10-12T15:00:41Z",
    "version": "v1",
    "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
    "pagination": {
      "records": { "limit": 25, "has_next": false, "has_previous": false },
      "navigation": { "next": null, "previous": null }
    }
  }
}
curl -X GET "https://api.sandbox.sovera.io/sovx/v1/customers/corp-redundant-firewall/credentials?filter[limit]=25" \
  -H "Authorization: Bearer YOUR_SESSION_TOKEN"

Errors: 401 UNAUTHORIZED missing or invalid session · 404 CUSTOMER_NOT_FOUND not owned by the session, or deleted · 422 VALIDATION_ERROR invalid filter, limit, or cursor (source.parameter names it).


Revoke Credential

DELETEhttps://api.sandbox.sovera.io/sovx/v1/customers/:customer_id/credentials/:credential_id

Revoke one credential. The key is rejected from the next request on, and it drops out of the list. Every user token and refresh token issued with this key is revoked too: re-issue them with the new key (POST /v1/users/tokens) before revoking the old one. Your dashboard session isn't affected. The id returned by older lists is still accepted. Account holder only.

DELETE https://api.sandbox.sovera.io/sovx/v1/customers/corp-redundant-firewall/credentials/a3f1c2d4-5e6f-4081-92a3-b4c5d6e7f809

Success Response (204 No Content)—empty body.

curl -X DELETE "https://api.sandbox.sovera.io/sovx/v1/customers/corp-redundant-firewall/credentials/a3f1c2d4-5e6f-4081-92a3-b4c5d6e7f809" \
  -H "Authorization: Bearer YOUR_SESSION_TOKEN"

Errors: 401 UNAUTHORIZED missing or invalid session · 403 ACCOUNT_OWNER_REQUIRED the session belongs to a team member, not the account holder · 404 CUSTOMER_NOT_FOUND not owned by the session, or deleted · 404 CREDENTIAL_NOT_FOUND no active credential with that id.

On this page