{"record":{"id":"83bcf2894279b3b6","repo":"juspay/hyperswitch","slug":"datatrans-requires-bodykey-auth-type","errorCode":null,"errorMessage":"Datatrans requires BodyKey auth type","messagePattern":"Datatrans requires BodyKey auth type","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/router/src/core/unified_connector_service/connector_config.rs","lineNumber":1057,"sourceCode":"                ConnectorAuthType::BodyKey { api_key, key1 } => Ok(Self::Bluesnap {\n                    username: key1.clone(),\n                    password: api_key.clone(),\n                }),\n                _ => Err(err(\"Bluesnap requires BodyKey auth type\")),\n            },\n            Connector::Cryptopay => match auth {\n                ConnectorAuthType::BodyKey { api_key, key1 } => Ok(Self::Cryptopay {\n                    api_key: api_key.clone(),\n                    api_secret: key1.clone(),\n                }),\n                _ => Err(err(\"Cryptopay requires BodyKey auth type\")),\n            },\n            Connector::Datatrans => match auth {\n                ConnectorAuthType::BodyKey { api_key, key1 } => Ok(Self::Datatrans {\n                    merchant_id: key1.clone(),\n                    password: api_key.clone(),\n                }),\n                _ => Err(err(\"Datatrans requires BodyKey auth type\")),\n            },\n            Connector::Globalpay => match auth {\n                ConnectorAuthType::BodyKey { api_key, key1 } => {\n                    let globalpay_meta = metadata\n                        .map(|m| {\n                            serde_json::from_value::<GlobalpayMetadata>(m.clone())\n                                .map_err(|_| err(\"Invalid Globalpay metadata format\"))\n                        })\n                        .transpose()?;\n\n                    Ok(Self::Globalpay {\n                        app_id: key1.clone(),\n                        app_key: api_key.clone(),\n                        account_name: globalpay_meta.and_then(|m| m.account_name),\n                    })\n                }\n                _ => Err(err(\"Globalpay requires BodyKey auth type\")),\n            },","sourceCodeStart":1039,"sourceCodeEnd":1075,"githubUrl":"https://github.com/juspay/hyperswitch/blob/afd92843521ced2c6856b98ae4ea332e75102d88/crates/router/src/core/unified_connector_service/connector_config.rs#L1039-L1075","documentation":"Hyperswitch's unified connector configuration converts a merchant's `ConnectorAuthType` into the connector-specific auth struct. Datatrans authenticates with credentials carried in the request body (merchant ID + password), so only `ConnectorAuthType::BodyKey` is accepted. Any other auth type produces this error via the catch-all match arm, converting the merchant connector into `Self::Datatrans` fails.","triggerScenarios":"Configuring the Datatrans connector with `ConnectorAuthType::SignatureKey`, `HeaderKey`, `CertificateKey`, `BodyKey` missing `key1`, or `NoKey`, then attempting a payment or connector-credential conversion in `connector_config.rs`.","commonSituations":"Merchant selects the wrong auth layout in the connector dashboard/API when adding Datatrans credentials; migration or seed data created credentials as HeaderKey; tenant config scripts pass api_key only without the required second key.","solutions":["Re-configure the Datatrans connector credential with `ConnectorAuthType::BodyKey`, mapping password/api_key to `api_key` and merchant_id to `key1`","Update the connector creation API call so `connector_type`/auth layout matches BodyKey (two fields)","If data was seeded wrongly, migrate existing merchant_connector_credentials rows for Datatrans to the BodyKey shape","Verify with a health/check call for the connector after re-saving credentials"],"exampleFix":"// before\nConnectorAuthType::HeaderKey { api_key }\n// after\nConnectorAuthType::BodyKey {\n    api_key: datatrans_password,\n    key1: datatrans_merchant_id,\n}","handlingStrategy":"validation","validationCode":"fn is_datatrans_auth(auth: &ConnectorAuthType) -> bool {\n    matches!(auth, ConnectorAuthType::BodyKey { .. })\n}\nif !is_datatrans_auth(&auth) {\n    return Err(report!(ConfigError::InvalidConnectorAuth(\"Datatrans requires BodyKey\")));\n}","typeGuard":"fn as_body_key(auth: &ConnectorAuthType) -> Option<(&String, &String)> {\n    match auth {\n        ConnectorAuthType::BodyKey { api_key, key1 } => Some((api_key, key1)),\n        _ => None,\n    }\n}","tryCatchPattern":"match build_connector_config(Connector::Datatrans, &auth, metadata) {\n    Ok(cfg) => use_config(cfg),\n    Err(e) if e.current_context().to_string().contains(\"BodyKey\") => {\n        // prompt re-entry of Datatrans credentials as BodyKey\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Use connector-specific auth-shape validators before saving credentials","Validate both BodyKey fields (api_key, key1) are non-empty at credential entry time","Keep connector auth templates aligned with the required type in connector_config.rs"],"tags":["rust","authentication","connector-config","datatrans"],"backgroundTag":"unsupported-enum-value","analyzedSha":"afd92843521ced2c6856b98ae4ea332e75102d88","analyzedAt":"2026-09-18T01:18:02.947Z","contentChangedAt":"2026-09-18T01:18:02.947Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}