OpenAPI 3.0 interactive documentation โ all endpoints with examples and cURL commands
Setup/management endpoints use Authorization: Bearer {accessToken}. Login validation endpoints use X-Temp-Token: {tempToken} issued after password verification.
No request body. Returns TOTP secret and otpauth:// URI for QR code.
{
"secret": "JBSWY3DPEHPK3PXP",
"qrUri": "otpauth://totp/eToro:user@email.com?secret=JBSWY3DPEHPK3PXP&issuer=eToro&algorithm=SHA1&digits=6&period=30",
"algorithm": "SHA1",
"digits": 6,
"period": 30
}
{ "error": "TOTP_ALREADY_ENABLED", "message": "TOTP is already configured" }
curl -X POST https://api.etoro.com/api/v1/2fa/totp/setup \ -H "Authorization: Bearer eyJhbGci..."
{ "code": "738204" }
| Field | Type | |
|---|---|---|
| code | string | REQUIRED โ 6-digit code from authenticator |
{
"enabled": true,
"method": "totp",
"backupCodes": ["A1B2-C3D4","E5F6-G7H8","I9J0-K1L2","M3N4-O5P6","Q7R8-S9T0","U1V2-W3X4","Y5Z6-A7B8","C9D0-E1F2","G3H4-I5J6","K7L8-M9N0"]
}
curl -X POST https://api.etoro.com/api/v1/2fa/totp/verify \
-H "Authorization: Bearer eyJhbGci..." \
-H "Content-Type: application/json" \
-d '{"code":"738204"}'
{ "code": "738204" }
{ "accessToken": "eyJhbGci...", "refreshToken": "eyJhbGci...", "expiresIn": 3600 }
401 { "error": "INVALID_TOTP_CODE", "message": "Invalid verification code", "attemptsRemaining": 4 } 401 { "error": "CODE_ALREADY_USED", "message": "This code has already been used" } 423 { "error": "ACCOUNT_LOCKED", "lockoutUntil": "2026-02-22T14:27:00Z" } 429 { "error": "RATE_LIMIT_EXCEEDED", "retryAfter": 300 }
curl -X POST https://api.etoro.com/api/v1/2fa/totp/validate \
-H "X-Temp-Token: temp_2fa_abc123" \
-H "Content-Type: application/json" \
-d '{"code":"738204"}'
// Request
{ "code": "738204" }
// Response 200
{ "disabled": true, "method": null }
Returns PublicKeyCredentialCreationOptions with residentKey: "required" for discoverable credentials (passwordless-ready). Excludes already-registered credentials via excludeCredentials.
{
"challenge": "dGVzdC1jaGFsbGVuZ2U...",
"rp": { "name": "eToro", "id": "etoro.com" },
"user": { "id": "MTIzNDU...", "name": "user@email.com", "displayName": "Yoni" },
"pubKeyCredParams": [
{ "type": "public-key", "alg": -7 },
{ "type": "public-key", "alg": -257 }
],
"timeout": 120000,
"attestation": "none",
"authenticatorSelection": {
"residentKey": "required",
"requireResidentKey": true,
"userVerification": "preferred",
"authenticatorAttachment": "platform"
},
"excludeCredentials": [
{ "id": "existing-cred-base64url", "type": "public-key", "transports": ["internal"] }
]
}
{ "error": "MAX_CREDENTIALS_REACHED", "message": "Maximum 10 passkeys registered" }
curl -X POST https://api.etoro.com/api/v1/2fa/passkey/register/options \ -H "Authorization: Bearer eyJhbGci..."
{
"attestation": {
"id": "credential-id-base64url",
"rawId": "Y3JlZGVudGlhbC1pZA...",
"response": {
"clientDataJSON": "eyJ0eXBl...",
"attestationObject": "o2NmbXR...",
"transports": ["internal", "hybrid"]
},
"type": "public-key",
"clientExtensionResults": { "credProps": { "rk": true } },
"authenticatorAttachment": "platform"
},
"deviceName": "iPhone 15 Pro"
}
{
"registered": true,
"credentialId": "credential-id-base64url",
"deviceName": "iPhone 15 Pro",
"deviceType": "multiDevice",
"backupEligible": true,
"backupState": true,
"transports": ["internal", "hybrid"]
}
curl -X POST https://api.etoro.com/api/v1/2fa/passkey/register/verify \
-H "Authorization: Bearer eyJhbGci..." \
-H "Content-Type: application/json" \
-d '{"attestation":{...},"deviceName":"iPhone 15 Pro"}'
2FA mode: Pass X-Temp-Token header โ returns allowCredentials with user's registered passkeys.
Passwordless mode: No auth โ returns empty allowCredentials for discoverable credential flow.
{
"challenge": "YXV0aC1jaGFsbGVuZ2U...",
"allowCredentials": [
{ "id": "cred-1-base64url", "type": "public-key", "transports": ["internal", "hybrid"] },
{ "id": "cred-2-base64url", "type": "public-key", "transports": ["usb"] }
],
"timeout": 120000,
"userVerification": "preferred",
"rpId": "etoro.com"
}
{
"challenge": "cGFzc3dvcmRsZXNz...",
"allowCredentials": [],
"timeout": 120000,
"userVerification": "required",
"rpId": "etoro.com"
}
curl -X POST https://api.etoro.com/api/v1/2fa/passkey/authenticate/options \ -H "X-Temp-Token: temp_2fa_abc123"
{
"assertion": {
"id": "credential-id-base64url",
"rawId": "Y3JlZGVudGlhbC1pZA...",
"response": {
"clientDataJSON": "eyJ0eXBl...",
"authenticatorData": "SZYN5YgO...",
"signature": "MEUCIQC...",
"userHandle": "MTIzNDU..."
},
"type": "public-key",
"clientExtensionResults": {},
"authenticatorAttachment": "platform"
}
}
{
"accessToken": "eyJhbGci...",
"refreshToken": "eyJhbGci...",
"expiresIn": 3600,
"credentialUsed": {
"id": "credential-id-base64url",
"deviceName": "iPhone 15 Pro"
}
}
401 { "error": "WEBAUTHN_VERIFICATION_FAILED", "message": "Passkey verification failed" } 401 { "error": "CREDENTIAL_NOT_FOUND", "message": "No matching credential" } 401 { "error": "COUNTER_MISMATCH", "message": "Possible cloned authenticator detected" }
curl -X POST https://api.etoro.com/api/v1/2fa/passkey/authenticate/verify \
-H "Content-Type: application/json" \
-d '{"assertion":{...}}'
{
"credentials": [
{
"id": "cred-id-1",
"deviceName": "iPhone 15 Pro",
"deviceType": "multiDevice",
"backupEligible": true,
"backupState": true,
"transports": ["internal", "hybrid"],
"lastUsed": "2026-02-22T10:30:00Z",
"createdAt": "2026-01-15T09:00:00Z"
},
{
"id": "cred-id-2",
"deviceName": "YubiKey 5",
"deviceType": "singleDevice",
"backupEligible": false,
"backupState": false,
"transports": ["usb", "nfc"],
"lastUsed": "2026-02-20T14:00:00Z",
"createdAt": "2026-02-01T11:00:00Z"
}
],
"maxCredentials": 10
}
curl https://api.etoro.com/api/v1/2fa/passkey/credentials \ -H "Authorization: Bearer eyJhbGci..."
{ "deleted": true, "credentialId": "cred-id-2", "remainingCredentials": 1 }
400 { "error": "CANNOT_DELETE_LAST_METHOD", "message": "Cannot delete last 2FA method" } 404 { "error": "CREDENTIAL_NOT_FOUND", "message": "Credential not found" }
curl -X DELETE https://api.etoro.com/api/v1/2fa/passkey/credentials/cred-id-2 \ -H "Authorization: Bearer eyJhbGci..." \ -H "X-2FA-Code: 738204"
{ "credentialId": "cred-id-1", "deviceName": "Work Phone" }
{ "credentialId": "cred-id-1", "deviceName": "Work Phone", "updated": true }
curl -X POST https://api.etoro.com/api/v1/2fa/passkey/rename \
-H "Authorization: Bearer eyJhbGci..." \
-H "Content-Type: application/json" \
-d '{"credentialId":"cred-id-1","deviceName":"Work Phone"}'
// Request โ requires current 2FA verification
{ "currentCode": "738204" }
// Response 200
{
"codes": ["A1B2-C3D4","E5F6-G7H8","I9J0-K1L2","M3N4-O5P6","Q7R8-S9T0","U1V2-W3X4","Y5Z6-A7B8","C9D0-E1F2","G3H4-I5J6","K7L8-M9N0"],
"warning": "Store these codes securely. Previous codes are now invalid."
}
// Request
{ "code": "A1B2-C3D4" }
// Response 200
{ "accessToken": "eyJhbGci...", "refreshToken": "eyJhbGci...", "codesRemaining": 9 }
{
"enabled": true,
"primaryMethod": "totp",
"totp": { "enabled": true, "configuredAt": "2026-02-22T14:00:00Z" },
"webauthn": {
"enabled": true,
"credentials": [{
"id": "cred-id-1", "deviceName": "iPhone 15 Pro",
"lastUsed": "2026-02-22T10:00:00Z", "createdAt": "2026-01-15T09:00:00Z", "backedUp": true
}]
},
"backupCodes": { "remaining": 8, "generatedAt": "2026-02-22T14:00:00Z" },
"recovery": { "email": "y***@etoro.com", "phone": "+972***1010" }
}
// Request
{ "email": "user@email.com", "identityProof": "base64-id-photo", "reason": "lost_device" }
// Response 202
{
"recoveryId": "rec-uuid-123", "status": "pending_review",
"estimatedTime": "24-48 hours",
"message": "Recovery request submitted. Check email for next steps."
}
{
"error": "ERROR_CODE", // Machine-readable error code
"message": "Human readable", // User-friendly message
"attemptsRemaining": 4, // Optional: remaining attempts
"retryAfter": 300, // Optional: seconds until retry
"lockoutUntil": "ISO-8601" // Optional: lockout expiry
}
| Code | HTTP | Description |
|---|---|---|
| INVALID_TOTP_CODE | 401 | TOTP code doesn't match |
| CODE_ALREADY_USED | 401 | Replay attack detected |
| INVALID_BACKUP_CODE | 401 | Backup code not found/used |
| WEBAUTHN_VERIFICATION_FAILED | 401 | WebAuthn assertion invalid |
| TOTP_ALREADY_ENABLED | 409 | TOTP already configured |
| MAX_CREDENTIALS_REACHED | 409 | Max 5 passkeys |
| ACCOUNT_LOCKED | 423 | Too many failures |
| RATE_LIMIT_EXCEEDED | 429 | Throttled |
| ENCRYPTION_ERROR | 500 | Vault/HSM failure |