User Data Storage - Integration Guide

This guide explains how to store and retrieve private user data using IBEX Safe's secure storage service. IBEX Safe is a regulated entity (VASP) compliant with GDPR, allowing your dApp to manage users' private data without ever storing it yourself.

📊 View Flow Diagram

Overview

The User Data API uses a generic proxy pattern to route requests to IBEX Safe. The IBEx.Fi API provides a transparent proxy endpoint that forwards requests to the IBEX Safe API, which handles the actual data storage and retrieval.

The proxy endpoints are:

For user data operations, you call:

The User Data API allows you to:

💡 Proxy Pattern :
🔒 Privacy & Security :

1. Store User Data

To store or update user data, use the POST /v1.1/ibexsafe/userdata endpoint. This routes through the generic proxy to IBEX Safe's /userdata endpoint.

Endpoint : POST /v1.1/ibexsafe/userdata (via generic proxy POST /v1.1/ibexsafe/:verb)

Headers :

Body (JSON) :

Request Example :

POST /v1.1/ibexsafe/userdata
Content-Type: application/json
Authorization: Bearer <access_token>

{
  "externalUserId": "c76302cb-f845-40f4-9c56-29710323afba",
  "data": {
    "email": "jane.doe@foo.domain",
    "firstName": "Jane",
    "lastName": "Doe",
    "language": "en",
    "optin.newsletter": true,
    "optin.walletAlerts": true,
    "private.apiKey": "secret-api-key-12345"
  }
}

Response (200 OK) :

{
  "success": true
}
💾 To Store :
💡 Note :

Common Use Cases

User Profile Information :

{
  "externalUserId": "c76302cb-f845-40f4-9c56-29710323afba",
  "data": {
    "email": "jane.doe@foo.domain",
    "firstName": "Jane",
    "lastName": "Doe",
    "phone": "+33612345678",
    "language": "en"
  }
}

Opt-in Preferences :

{
  "externalUserId": "c76302cb-f845-40f4-9c56-29710323afba",
  "data": {
    "optin.newsletter": true,
    "optin.walletAlerts": true,
    "optin.marketing": false
  }
}

Private/Sensitive Data :

{
  "externalUserId": "c76302cb-f845-40f4-9c56-29710323afba",
  "data": {
    "private.apiKey": "secret-key-12345",
    "private.encryptionKey": "encrypted-data-here",
    "private.customSecret": "sensitive-information"
  }
}
⚠️ Important : Keys prefixed with private. are write-only. They can be stored but will never be returned when retrieving user data. Use this for sensitive information that should never be exposed via GET requests.

2. Retrieve User Data

To retrieve stored user data, use the GET /v1.1/ibexsafe/userdata/external/:externalUserId endpoint. This routes through the generic proxy to IBEX Safe's /userdata/external/:externalUserId endpoint.

Endpoint : GET /v1.1/ibexsafe/userdata/external/:externalUserId (via generic proxy GET /v1.1/ibexsafe/:verb)

Headers :

Path Parameters :

Request Example :

GET /v1.1/ibexsafe/userdata/external/c76302cb-f845-40f4-9c56-29710323afba
Authorization: Bearer <access_token>

Response (200 OK) :

{
  "email": "jane.doe@foo.domain",
  "firstName": "Jane",
  "lastName": "Doe",
  "language": "en",
  "optin.newsletter": true,
  "optin.walletAlerts": true
}
💡 Note :

Fallback: POST for Reading

If the GET endpoint returns 401 Unauthorized, you can use POST as a fallback:

Endpoint : POST /v1.1/ibexsafe/userdata

Body (JSON) :

{
  "externalUserId": "c76302cb-f845-40f4-9c56-29710323afba",
  "data": {}
}

Response (200 OK) :

{
  "email": "jane.doe@foo.domain",
  "firstName": "Jane",
  "lastName": "Doe",
  "language": "en",
  "optin.newsletter": true,
  "optin.walletAlerts": true
}

3. Update User Data

To update existing user data, use the same POST /v1.1/ibexsafe/userdata endpoint with partial data. Only the keys you include will be updated.

Request Example (Partial Update) :

POST /v1.1/ibexsafe/userdata
Content-Type: application/json
Authorization: Bearer <access_token>

{
  "externalUserId": "c76302cb-f845-40f4-9c56-29710323afba",
  "data": {
    "language": "fr",
    "optin.newsletter": false
  }
}

Response (200 OK) :

{
  "success": true
}
💡 Note : Partial updates are supported. You only need to include the keys you want to update. Other keys remain unchanged.

Delete a Key

To delete a key, set its value to null:

POST /v1.1/ibexsafe/userdata
Content-Type: application/json
Authorization: Bearer <access_token>

{
  "externalUserId": "c76302cb-f845-40f4-9c56-29710323afba",
  "data": {
    "phone": null,
    "optin.marketing": null
  }
}

4. Integration with Sign-In

You can optionally include user data in the sign-in response by setting includeUserdata: true in the sign-in request body:

Request Example :

POST /v1.2/auth/sign-in
Content-Type: application/json

{
  "credential": { ... },
  "includeUserdata": true
}

Response (200 OK) :

{
  "access_token": "...",
  "refresh_token": "...",
  "safeAddress": { ... },
  "userdata": {
    "email": "jane.doe@foo.domain",
    "firstName": "Jane",
    "lastName": "Doe",
    "language": "en",
    "optin.newsletter": true,
    "optin.walletAlerts": true
  }
}
💡 Note : This is optional. If includeUserdata is not set or is false, the userdata field will not be included in the response.

5. Error Handling

401 Unauthorized

If the JWT is missing or invalid, you will receive a 401 error. Make sure to include a valid Authorization header.

400 Bad Request

If the request body is malformed or externalUserId doesn't match the authenticated user, you will receive a 400 error.

404 Not Found

If the user data doesn't exist, GET requests return 204 No Content (not 404).

6. Complete Flow Summary

  1. Store initial data : POST /v1.1/ibexsafe/userdata with user data
  2. Retrieve data : GET /v1.1/ibexsafe/userdata/external/:externalUserId to get stored data
  3. Update data : POST /v1.1/ibexsafe/userdata with partial updates as needed
  4. Optional: Include in sign-in : Set includeUserdata: true in sign-in requests
⚠️ Important Points :

Technical Deep Dive - For AI Integration

This section provides detailed technical information for AI systems integrating the IBEX User Data storage flow, including architecture patterns, data models, and implementation details.

User Data Storage - Technical Details

Generic Proxy Pattern

POST /v1.1/ibexsafe/userdata

GET /v1.1/ibexsafe/userdata/external/:externalUserId

Data Model

User Data Structure:

{
  "externalUserId": "string (UUID)",
  "data": {
    "key1": "string | boolean | number | null",
    "key2": "string | boolean | number | null",
    "private.secretKey": "string | boolean | number | null"  // Write-only
  }
}

Common Keys (Examples):

Privacy & Security

Private Keys:

GDPR Compliance:

Integration Points

Sign-In Integration:

WebSocket Integration:

Error Handling

Key Implementation Files

Complete Flow - Technical Sequence

  1. Store data : POST /v1.1/ibexsafe/userdata with { externalUserId, data: { key: value } }
  2. Proxy to IBEX Safe : API forwards request to IBEX Safe upstream
  3. Data stored : IBEX Safe stores data securely (GDPR-compliant)
  4. Retrieve data : GET /v1.1/ibexsafe/userdata/external/:externalUserId
  5. Proxy to IBEX Safe : API forwards GET request to IBEX Safe
  6. Filter private keys : IBEX Safe excludes private.* keys from response
  7. Return data : API returns flat key/value map to client
  8. Update data : POST /v1.1/ibexsafe/userdata with partial updates
  9. Delete key : Set key to null in update request
← Back to Main Guide