# Credentials ## Create new API client credentials - [POST /v1/credentials](https://developers.bcb.bm/apis/open-banking-api/open-banking-api/credentials/credentials_post.md): Creates new API client credentials based on an existing client's permissions and configuration. The new credentials will inherit the same roles and permissions as the specified existing client. Key Features: - A new client ID (GUID) is generated automatically - A cryptographically secure password (22-30 characters) is generated automatically - A cryptographically secure message signing secret (32 bytes) is generated automatically for HMAC-SHA256 signing - All roles and direct permissions are copied from the existing client - The new credentials can have different IP restrictions if specified Password Security: - Generated passwords are 22-30 characters long for enhanced security - Include uppercase letters, lowercase letters, digits, and special characters - The generated password is only returned once in the response Message Signing Secret: - A 32-byte (256-bit) random key (Base64 encoded) is generated for signing API requests - This key will be used by the system to sign callback responses - notifications, background job webhooks - The secret is returned only once in the response Access Control: - You can only create credentials based on clients you have access to - New client inherits exact role and permission set from source client - IP restrictions can be customized or inherited from source client ### Base URL: All API requests use the versioned base URL: https://api.bcb.bm/v1/credentials ### Idempotency The API supports idempotency through the optional Idempotency-Key header: - If no idempotency key is provided, the request is processed normally (duplicates are possible) - If a valid UUID idempotency key is provided for a new transaction, the system stores the key and associates it with the transaction results - If the same idempotency key is received again for the same endpoint/action, the system returns the previously stored response - Idempotency keys are user-specific - different users with the same keys don't share cached responses - The idempotency key must be a valid UUID format (e.g., "123e4567-e89b-12d3-a456-426614174000"). ### Sample Request in JavaScript: javascript async function createCredentials() { try { const token = localStorage.getItem('jwt'); // Your JWT token from authentication const response = await fetch('https://api.bcb.bm/v1/credentials', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': Bearer ${token} }, body: JSON.stringify({ allowedIps: '192.168.1.100,10.0.0.0/24' // Optional: specify IP restrictions, or omit/'*' for all IPs }) }); if (!response.ok) { const errorData = await response.json(); throw new Error(Error: ${errorData.message || response.statusText}); } const data = await response.json(); console.log('New credentials created:', { clientId: data.clientId, clientSecret: data.clientSecret, // Save this securely - only shown once! messageSigningSecret: data.messageSigningSecret, // Save this securely - only shown once! isActive: data.isActive, allowedIps: data.allowedIps }); // Store new credentials securely // WARNING: This is just an example - use secure storage in production localStorage.setItem('newClientId', data.clientId); localStorage.setItem('newClientSecret', data.clientSecret); localStorage.setItem('newMessageSigningSecret', data.messageSigningSecret); } catch (error) { console.error('Error creating credentials:', error); } } createCredentials(); Required Permission: manage-credentials This endpoint requires the permission claim manage-credentials to be present in the JWT token. These permissions are embedded in the token during the authentication process and cannot be modified afterward. The token must be obtained with the appropriate permissions to access this endpoint. ## Rotate the client secret for an existing API client - [PATCH /v1/credentials/{clientId}](https://developers.bcb.bm/apis/open-banking-api/open-banking-api/credentials/credentials_patch.md): Rotates (changes) the client secret AND the message signing secret for an existing API client while preserving all other settings. This is useful for credential rotation policies, security incident response, or regular maintenance. Key Features: - A new cryptographically secure password (22-30 characters) is generated automatically - A new cryptographically secure message signing secret (32 bytes) is generated automatically - The existing client's secrets are immediately replaced with the new ones - All roles, permissions, and other settings remain unchanged - The old secrets become invalid immediately after successful rotation - The new secrets are returned in the response (only shown once) Password Security: - Generated passwords are 22-30 characters long for enhanced security - Include uppercase letters, lowercase letters, digits, and special characters - The new password is only returned once in the response Access Control: - You can only rotate secrets for clients you have access to - The rotated client retains all existing roles and permissions Important Security Notes: - The old secret stops working immediately after successful rotation - Any applications using the old secret will need to be updated with the new secret - Store the new secret securely as it won't be shown again ### Base URL: All API requests use the versioned base URL: https://api.bcb.bm/v1/credentials/{clientId} ### Idempotency The API supports idempotency through the optional Idempotency-Key header: - If no idempotency key is provided, the request is processed normally (duplicates are possible) - If a valid UUID idempotency key is provided for a new transaction, the system stores the key and associates it with the transaction results - If the same idempotency key is received again for the same endpoint/action, the system returns the previously stored response - Idempotency keys are user-specific - different users with the same keys don't share cached responses - The idempotency key must be a valid UUID format (e.g., "123e4567-e89b-12d3-a456-426614174000"). ### Sample Request in JavaScript: javascript async function rotateClientSecret(clientId) { try { const token = localStorage.getItem('jwt'); // Your JWT token from authentication const response = await fetch(https://api.bcb.bm/v1/credentials/${clientId}, { method: 'PATCH', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': Bearer ${token} } }); if (!response.ok) { const errorData = await response.json(); throw new Error(Error: ${errorData.message || response.statusText}); } const data = await response.json(); console.log('Client secret rotated successfully:', { clientId: data.clientId, newClientSecret: data.clientSecret, // Save this securely - only shown once! newMessageSigningSecret: data.messageSigningSecret, // Save this securely - only shown once! isActive: data.isActive, allowedIps: data.allowedIps }); // Update stored credentials securely // WARNING: This is just an example - use secure storage in production localStorage.setItem('clientSecret', data.clientSecret); localStorage.setItem('messageSigningSecret', data.messageSigningSecret); // Important: Update any applications using the old secret console.warn('IMPORTANT: Update all applications using this client with the new secret!'); } catch (error) { console.error('Error rotating client secret:', error); } } // Example usage rotateClientSecret('12345678-1234-1234-1234-123456789abc'); Required Permission: manage-credentials This endpoint requires the permission claim manage-credentials to be present in the JWT token. These permissions are embedded in the token during the authentication process and cannot be modified afterward. The token must be obtained with the appropriate permissions to access this endpoint. ## Disable an existing API client - [DELETE /v1/credentials/{clientId}](https://developers.bcb.bm/apis/open-banking-api/open-banking-api/credentials/credentials_delete.md): Disables an existing API client, immediately preventing any further authentication using that client ID and secret. This operation also revokes all active tokens associated with the client. Key Features: - Disables the credentials instantly – all authentication requests will fail after this operation - Revokes all active tokens immediately for enhanced security - Idempotent: calling the endpoint on an already inactive client returns success Security Considerations: - All active tokens are immediately invalidated and removed from the system - Any applications using the disabled client will lose access immediately - The client record is preserved for audit and compliance purposes Access Control: - You can only disable clients that belong to your organization ### Base URL: All API requests use the versioned base URL: https://api.bcb.bm/v1/credentials/{clientId} ### Sample Request in JavaScript: javascript async function disableClient(clientId) { try { const token = localStorage.getItem('jwt'); // Your JWT token from authentication const response = await fetch(https://api.bcb.bm/v1/credentials/${clientId}, { method: 'DELETE', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': Bearer ${token} } }); if (!response.ok) { const errorData = await response.json(); throw new Error(Error: ${errorData.message || response.statusText}); } const data = await response.json(); console.log('Client disabled successfully:', { clientId: data.clientId, isActive: data.isActive, // Should be false allowedIps: data.allowedIps }); // Important: Update any applications that were using this client console.warn('IMPORTANT: All applications using this client will lose access immediately!'); } catch (error) { console.error('Error disabling client:', error); } } // Example usage disableClient('12345678-1234-1234-1234-123456789abc'); Required Permission: manage-credentials This endpoint requires the permission claim manage-credentials to be present in the JWT token. These permissions are embedded in the token during the authentication process and cannot be modified afterward. The token must be obtained with the appropriate permissions to access this endpoint. ## Get permissions for an existing API client - [GET /v1/credentials/{clientId}/permissions](https://developers.bcb.bm/apis/open-banking-api/open-banking-api/credentials/credentials_getpermissions.md): Retrieves all permissions assigned to the specified API client. The response provides a comprehensive view of what features the client can access. Key Features: - Returns all permissions assigned to the client - Results are sorted alphabetically by permission key for consistent ordering - Includes human-readable descriptions for each permission Access Control: - You can only view permissions for clients that belong to your organization Use Cases: - Audit client access capabilities - Troubleshoot authentication and authorization issues - Verify client configuration during security reviews - Document client permissions for compliance purposes ### Base URL: All API requests use the versioned base URL: https://api.bcb.bm/v1/credentials/{clientId}/permissions ### Sample Request in JavaScript: javascript async function getClientPermissions(clientId) { try { const token = localStorage.getItem('jwt'); // Your JWT token from authentication const response = await fetch(https://api.bcb.bm/v1/credentials/${clientId}/permissions, { method: 'GET', headers: { 'Accept': 'application/json', 'Authorization': Bearer ${token} } }); if (!response.ok) { const errorData = await response.json(); throw new Error(Error: ${errorData.message || response.statusText}); } const permissions = await response.json(); console.log('Client permissions:', permissions); // Display permissions in a user-friendly format permissions.forEach(permission => { console.log(- ${permission.key}: ${permission.description || 'No description available'}); }); return permissions; } catch (error) { console.error('Error retrieving client permissions:', error); } } // Example usage getClientPermissions('12345678-1234-1234-1234-123456789abc'); Required Permission: manage-credentials This endpoint requires the permission claim manage-credentials to be present in the JWT token. These permissions are embedded in the token during the authentication process and cannot be modified afterward. The token must be obtained with the appropriate permissions to access this endpoint. ## Get public key metadata - [GET /v1/credentials/{clientId}/keys](https://developers.bcb.bm/apis/open-banking-api/open-banking-api/credentials/credentials_getkeys.md): Returns metadata for the partner RSA keys: - Indicates whether primary/secondary keys exist - Provides short fingerprints, algorithms, and last-updated timestamps - Shows verification status of the secondary key (after proof-of-possession) ### Sample Request in JavaScript: javascript async function getKeyMetadata(clientId) { try { const token = localStorage.getItem('jwt'); const response = await fetch(https://api.bcb.bm/v1/credentials/${clientId}/keys, { method: 'GET', headers: { 'Accept': 'application/json', 'Authorization': Bearer ${token} } }); if (!response.ok) { const errorData = await response.json(); throw new Error(Error: ${errorData.message || response.statusText}); } const metadata = await response.json(); console.log('Key metadata:', { hasPrimaryKey: metadata.hasPrimaryKey, hasSecondaryKey: metadata.hasSecondaryKey, primaryKeyFingerprint: metadata.primaryKeyFingerprint, secondaryKeyFingerprint: metadata.secondaryKeyFingerprint, secondaryKeyVerified: metadata.secondaryKeyVerified }); return metadata; } catch (error) { console.error('Error getting key metadata:', error); } } getKeyMetadata('12345678-1234-1234-1234-123456789abc'); Required Permission: manage-credentials This endpoint requires the permission claim manage-credentials to be present in the JWT token. These permissions are embedded in the token during the authentication process and cannot be modified afterward. The token must be obtained with the appropriate permissions to access this endpoint. ## Upload secondary public key - [PUT /v1/credentials/{clientId}/keys/secondary](https://developers.bcb.bm/apis/open-banking-api/open-banking-api/credentials/credentials_putsecondarykey.md): Upload a new RSA public key (PEM format) into the secondary slot to stage rotation. Key Features: - Accepts RSA public keys (2048-bit minimum recommended) - Resets verification status when a new key is uploaded - Secondary key becomes active for signature verification alongside primary Rotation flow: 1. Upload secondary key (this endpoint) 2. POST challenge → sign locally → POST verify 3. POST promote (makes secondary the primary) 4. (Optional) DELETE secondary if aborting ### Sample Request in JavaScript: javascript async function uploadSecondaryKey(clientId, publicKeyPem) { try { const token = localStorage.getItem('jwt'); const response = await fetch(https://api.bcb.bm/v1/credentials/${clientId}/keys/secondary, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': Bearer ${token} }, body: JSON.stringify({ publicKeyPem: publicKeyPem }) }); if (!response.ok) { const errorData = await response.json(); throw new Error(Error: ${errorData.message || response.statusText}); } const metadata = await response.json(); console.log('Secondary key uploaded:', { hasSecondaryKey: metadata.hasSecondaryKey, secondaryKeyFingerprint: metadata.secondaryKeyFingerprint, secondaryKeyVerified: metadata.secondaryKeyVerified // Will be false until verified }); return metadata; } catch (error) { console.error('Error uploading secondary key:', error); } } Required Permission: manage-credentials This endpoint requires the permission claim manage-credentials to be present in the JWT token. These permissions are embedded in the token during the authentication process and cannot be modified afterward. The token must be obtained with the appropriate permissions to access this endpoint. ## Delete secondary public key - [DELETE /v1/credentials/{clientId}/keys/secondary](https://developers.bcb.bm/apis/open-banking-api/open-banking-api/credentials/credentials_deletesecondarykey.md): Removes the secondary key from the staging slot. Useful for aborting rotation or correcting mistakes before promotion. Key Features: - Clears the secondary key slot - Idempotent: returns success even if secondary key doesn't exist - Safe for retries ### Sample Request in JavaScript: javascript async function deleteSecondaryKey(clientId) { try { const token = localStorage.getItem('jwt'); const response = await fetch(https://api.bcb.bm/v1/credentials/${clientId}/keys/secondary, { method: 'DELETE', headers: { 'Accept': 'application/json', 'Authorization': Bearer ${token} } }); if (!response.ok) { const errorData = await response.json(); throw new Error(Error: ${errorData.message || response.statusText}); } const metadata = await response.json(); console.log('Secondary key deleted:', { hasSecondaryKey: metadata.hasSecondaryKey // Now false }); return metadata; } catch (error) { console.error('Error deleting secondary key:', error); } } Required Permission: manage-credentials This endpoint requires the permission claim manage-credentials to be present in the JWT token. These permissions are embedded in the token during the authentication process and cannot be modified afterward. The token must be obtained with the appropriate permissions to access this endpoint. ## Promote secondary key to primary - [POST /v1/credentials/{clientId}/keys/promote](https://developers.bcb.bm/apis/open-banking-api/open-banking-api/credentials/credentials_promotesecondarykey.md): Promotes the current secondary key to primary and clears the secondary slot. Use after validating the new key (optionally after challenge/verify). Key Features: - Makes the secondary key the new primary - Clears the secondary slot - Previous primary key is replaced ### Sample Request in JavaScript: javascript async function promoteSecondaryKey(clientId) { try { const token = localStorage.getItem('jwt'); const response = await fetch(https://api.bcb.bm/v1/credentials/${clientId}/keys/promote, { method: 'POST', headers: { 'Accept': 'application/json', 'Authorization': Bearer ${token} } }); if (!response.ok) { const errorData = await response.json(); throw new Error(Error: ${errorData.message || response.statusText}); } const metadata = await response.json(); console.log('Secondary key promoted to primary:', { hasPrimaryKey: metadata.hasPrimaryKey, hasSecondaryKey: metadata.hasSecondaryKey, // Now false primaryKeyFingerprint: metadata.primaryKeyFingerprint // Updated }); return metadata; } catch (error) { console.error('Error promoting secondary key:', error); } } Required Permission: manage-credentials This endpoint requires the permission claim manage-credentials to be present in the JWT token. These permissions are embedded in the token during the authentication process and cannot be modified afterward. The token must be obtained with the appropriate permissions to access this endpoint. ## Generate secondary key challenge - [POST /v1/credentials/{clientId}/keys/secondary/challenge](https://developers.bcb.bm/apis/open-banking-api/open-banking-api/credentials/credentials_requestsecondarykeychallenge.md): Returns a time-limited challenge (Base64) that must be signed with the private key corresponding to the secondary public key. Proves ownership before promotion. Challenge Format: - Base64 encoding of: {clientId}.{nonce}.{expiry}.{keyFingerprint} - Sign the decoded raw bytes of this challenge (not the Base64 literal). - Valid for ~5 minutes - Bound to the current secondary key (fingerprint included) ### Sample Request in JavaScript: javascript async function requestChallenge(clientId) { try { const token = localStorage.getItem('jwt'); const response = await fetch(https://api.bcb.bm/v1/credentials/${clientId}/keys/secondary/challenge, { method: 'POST', headers: { 'Accept': 'application/json', 'Authorization': Bearer ${token} } }); if (!response.ok) { const errorData = await response.json(); throw new Error(Error: ${errorData.message || response.statusText}); } const { challenge, expiresUtc } = await response.json(); console.log('Challenge received:', { challenge, expiresUtc }); // Sign the challenge with your private key const crypto = require('crypto'); const privateKeyPem = process.env.PRIVATE_KEY; const sign = crypto.createSign('RSA-SHA256'); sign.update(Buffer.from(challenge, 'base64')); const signature = sign.sign({ key: privateKeyPem, padding: crypto.constants.RSA_PKCS1_PSS_PADDING, saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST }, 'base64'); console.log('Signature created, ready for verification'); return { challenge, signature }; } catch (error) { console.error('Error requesting challenge:', error); } } Required Permission: manage-credentials This endpoint requires the permission claim manage-credentials to be present in the JWT token. These permissions are embedded in the token during the authentication process and cannot be modified afterward. The token must be obtained with the appropriate permissions to access this endpoint. ## Verify secondary key ownership - [POST /v1/credentials/{clientId}/keys/secondary/verify](https://developers.bcb.bm/apis/open-banking-api/open-banking-api/credentials/credentials_verifysecondarykeychallenge.md): Submit the Base64 challenge and its RSA-PSS signature (SHA-256). Important: sign the decoded raw bytes of the challenge, not the Base64 string literal. On success, the secondary key is marked as verified. Key Features: - Validates signature using RSA-PSS + SHA-256 - Checks challenge expiry (5-minute window) - Verifies challenge matches current secondary key - Sets secondaryKeyVerified: true on success ### Sample Request in JavaScript: javascript async function verifySecondaryKey(clientId, challenge, signature) { try { const token = localStorage.getItem('jwt'); const response = await fetch(https://api.bcb.bm/v1/credentials/${clientId}/keys/secondary/verify, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': Bearer ${token} }, body: JSON.stringify({ challenge: challenge, signature: signature }) }); if (!response.ok) { const errorData = await response.json(); throw new Error(Error: ${errorData.message || response.statusText}); } const metadata = await response.json(); if (metadata.secondaryKeyVerified) { console.log('✓ Secondary key verified successfully!'); console.log('You can now promote it to primary or test with production traffic.'); } else { console.error('✗ Verification failed - signature did not match'); } return metadata; } catch (error) { console.error('Error verifying secondary key:', error); } } // Complete rotation flow example: // 1. Upload: await uploadSecondaryKey(clientId, publicKeyPem); // 2. Challenge: const { challenge, signature } = await requestChallenge(clientId); // 3. Verify: await verifySecondaryKey(clientId, challenge, signature); // 4. Promote: await promoteSecondaryKey(clientId); Required Permission: manage-credentials This endpoint requires the permission claim manage-credentials to be present in the JWT token. These permissions are embedded in the token during the authentication process and cannot be modified afterward. The token must be obtained with the appropriate permissions to access this endpoint.