API Migration Guide
Breaking Changes
1. Base URL Changed
| Old | New |
|---|---|
/transfer_agent_api/v1/ | /api/v1/ |
2. Authentication Headers Renamed
| Old Header | New Header |
|---|---|
X-Request-Sk-Base64 / X-Request-Signature-Base64 | X-Request-Sig-B64 |
X-Api-Key-Base64 | X-Api-Key |
3. Endpoint Paths Changed
| Old | New |
|---|---|
POST /transfer_agent_api/v1/approve_investor | POST /api/v1/investor/whitelist |
GET /transfer_agent_api/v1/check_whitelist/{address} | GET /api/v1/investor/whitelist_status/{wallet_address} |
4. Endpoints Removed
| Endpoint | Description |
|---|---|
POST /transfer_agent_api/v1/propose_tx | Safe transaction proposal |
POST /transfer_agent_api/v1/get_nonce | Transaction queue slot |
5. Response Field Renamed
Check whitelist status:
| Old | New |
|---|---|
whitelisted | isWhitelisted |
6. Required Request Fields
The new API enforces validation on investor fields:
id,first_name,last_name,email,dob,full_address,tin,blockchain_wallet,primary_phoneare requiredfull_addressrequires:street,city,countryCode,postalCode
New Features
1. New Endpoints
| Endpoint | Purpose | Auth Required |
|---|---|---|
POST /api/v1/investor/kyc | Submit KYC data without whitelisting | Yes |
GET /api/v1/callback_pk | Get public key for callback signature verification | No |
GET /api/v1/health | Health check | No |
2. File Upload Support
New optional fields on investor object:
{
"identityDocument": {
"fileName": "passport.jpg",
"contentType": "image/jpeg",
"size": 102400,
"data": "base64-encoded-content"
},
"proofOfAddress": {
"fileName": "utility_bill.pdf",
"contentType": "application/pdf",
"size": 204800,
"data": "base64-encoded-content"
}
}
3. Additional Investor Fields (Optional)
| Field | Type | Description |
|---|---|---|
accreditation | "accredited" | "non_accredited" | "pending" | Accreditation status |
ssn | string | Social Security Number (US investors) |
passportNumber | string | Passport number (non-US investors) |
identityDocumentCountry | string | ISO 3166-1 alpha-2 country code |
All fields above are optional and can be omitted from requests.
4. External KYC Verification Status
New optional fields on request body:
| Field | Type | Description |
|---|---|---|
verifiedStatus | boolean | Whether KYC verification passed (default: true) |
verifiedAt | ISO 8601 string | When verification was completed (default: current timestamp) |
5. Enhanced Response Structure
Whitelist/KYC response now includes:
{
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"status": "QUEUED",
"message": "Whitelisting request accepted and queued for processing"
}
Check whitelist response now includes:
{
"requestId": "uuid",
"address": "wallet_address",
"isWhitelisted": true,
"whitelistGroupId": 1,
"walletGroup": 1
}
6. Standardized Status Enum
| Status | Description |
|---|---|
QUEUED | Request accepted, awaiting processing |
PENDING | Processing in progress |
SUCCESS | Completed successfully |
FAILED | Processing failed |
7. Detailed Failure Reasons
When status: "FAILED", the reason field contains:
| Reason | Description |
|---|---|
INVALID_MESSAGE | Request validation failed |
PII_STORAGE_ERROR | Failed to store investor data |
ALREADY_WHITELISTED | Wallet already whitelisted |
SIGNING_NOT_ALLOWED | Signing permission denied |
SIGNING_ERROR | Transaction signing failed |
BROADCAST_SUBMIT_ERROR | Failed to submit transaction |
BROADCAST_FAILED | Transaction broadcast failed |
CALLBACK_DELIVERY_FAILED | Callback delivery failed |
8. Standardized Error Response
All errors now return:
{
"error": "BAD_REQUEST|UNAUTHORIZED|FORBIDDEN|NOT_FOUND|INTERNAL_ERROR",
"details": "Human-readable error message",
"requestId": "uuid (if available)"
}
Edge Case Handling Differences
Already Whitelisted Wallets
| Aspect | Old API | New API |
|---|---|---|
| Pre-check | No pre-check before submitting | Checks on-chain status before signing |
| Behavior | May attempt duplicate transaction | Returns ALREADY_WHITELISTED via callback |
| Response | Transaction would fail on-chain | Fails early, no wasted gas |
New API behavior: Before signing a whitelist transaction, the new API checks if the wallet is already in the target whitelist group. If so, it immediately returns a FAILED callback with reason: "ALREADY_WHITELISTED" without attempting the transaction.
Whitelist Status Response
| Old API | New API |
|---|---|
{ whitelisted: boolean } | { isWhitelisted, whitelistGroupId, walletGroup } |
The new API returns the expected group (whitelistGroupId from config) and the actual on-chain group (walletGroup), allowing clients to detect group mismatches.
Request Ordering (FIFO)
| Old API | New API |
|---|---|
| No ordering guarantees | FIFO queue per investor ID |
The new API uses investor.id as the message group ID, ensuring requests for the same investor are processed in order.
File Upload Validation
New API validates file uploads synchronously and returns specific error codes:
| Error Code | Description |
|---|---|
INVALID_REQUEST | Missing required file metadata (fileName, contentType, size, data) |
INVALID_DATA | File data is not valid base64 |
SIZE_MISMATCH | Declared size doesn't match decoded file size |
Server Configuration
| Environment | URL |
|---|---|
| Production | https://ta.upside.gg |
| Staging | https://ta-staging.upside.gg |