juspay/hyperswitch · error · Error
API Key create call failed with status ${response.status} an
Error message
API Key create call failed with status ${response.status} and message: "${response.body.error.message}" What it means
Thrown by the apiKeyCreateTest command (cypress-tests/cypress/support/commands.js:1383) when POST {baseUrl}/api_keys/{merchantId} returns non-200. The call authenticates with globalState.get('adminApiKey') (the admin key, not the merchant key), sets expiration to tomorrow via isoTimeTomorrow(), and on success stores apiKeyId/api_key into globalState — so this failure cascades into every later command that needs a merchant api-key.
Source
Thrown at cypress-tests/cypress/support/commands.js:1383
cy.wrap(response).then(() => {
if (response.status === 200) {
expect(response.body.merchant_id).to.equal(merchantId);
expect(response.body.description).to.equal(
apiKeyCreateBody.description
);
// API Key assertions are intentionally excluded to avoid being exposed in the logs
expect(response.body).to.have.property(keyIdType).and.to.include(keyId)
.and.to.not.be.empty;
globalState.set("apiKeyId", response.body.key_id);
globalState.set("apiKey", response.body.api_key);
cy.task("setGlobalState", globalState.data);
} else {
// to be updated
throw new Error(
`API Key create call failed with status ${response.status} and message: "${response.body.error.message}"`
);
}
});
});
});
Cypress.Commands.add("apiKeyUpdateCall", (apiKeyUpdateBody, globalState) => {
const merchantId = globalState.get("merchantId");
const apiKeyId = globalState.get("apiKeyId");
// We do not want to keep API Key forever,
// so we set the expiry to tomorrow as new merchant accounts are created with every run
const expiry = isoTimeTomorrow();
// Update request body
apiKeyUpdateBody.expiration = expiry;
cy.request({View on GitHub (pinned to 9b8b89dc37)
Solutions
- Verify the admin API key env var is set, current, and belongs to the same environment as baseUrl
- Confirm globalState.get('merchantId') came from a successful merchant-create step in this run
- Grab the logged x-request-id and inspect the server logs for the exact rejection
- Check the apiKeyCreateBody fixture (description/name) matches the current api_keys schema
- Fix credentials and re-run — all subsequent steps depend on apiKeyId/api_key this command sets
Defensive patterns
Strategy: try-catch
Validate before calling
if (!globalState.get('adminApiKey')) {
throw new Error('adminApiKey missing from globalState — check env/secrets before apiKeyCreateTest');
} Try / catch
cy.on('fail', (err) => {
if (err.message.includes('API Key create call failed')) {
throw new Error(`Setup gate: API key provisioning failed — every later step needs apiKey/apiKeyId. Root cause: ${err.message}`);
}
throw err;
}); Prevention
- Fail fast on a missing adminApiKey before the run starts
- Treat this command as a gate: everything after it depends on apiKeyId/api_key
- Rotate secrets before launching a long suite, not midway
When it happens
Trigger: Invalid or expired adminApiKey (401); merchantId missing or deleted so the URL targets a non-existent resource (404); server rejecting the expiration/description body (400); 5xx from the api_keys service; validateEnv(baseUrl, 'key_id') misconfiguration producing a malformed request.
Common situations: The admin API key env var was rotated between runs; CI secrets not injected so adminApiKey is undefined; the merchant record was purged on the target environment; the env key-id prefix doesn't match what the environment issues, breaking the success-path assertions after a 200.
Related errors
- Unsupported keyIdType: ${keyIdType}
- Business Profile call failed ${response.body.error.message}
- Business Profile Update Failed: ${response.body.error?.messa
- No credentials found for ${connectorName} in creds.json — sk
- Connector Create Call Failed ${response.body.error.message}
AI-assisted analysis of juspay/hyperswitch@9b8b89dc37 (2026-08-16).
Data as JSON: /api/errors/bcbd9a650e664885.
Report an issue: GitHub.