---
title: "API for E2E test automation"
description: "Retrieve SMS, email and TOTP verification codes with one REST call inside Playwright, Cypress or Selenium tests. Keep MFA enabled in every environment."
url: "https://get.mymfa.io/features/test-automation"
canonical: "https://get.mymfa.io/features/test-automation"
markdown: "https://get.mymfa.io/features/test-automation.md"
author: "Jonathan Bernales"
publisher: "GetMyMFA"
date_published: "2024-09-01"
date_modified: "2026-09-27"
---

# API for E2E test automation

> **TL;DR** The GetMyMFA REST API returns the latest MFA code for a virtual phone number, email address or TOTP token with one GET request authenticated by an x-api-key header. Call /v1/{phoneId}/mfa/latest after your test triggers the login, read the mfaCode field and fill it in. Works with Playwright, Cypress, Selenium or any HTTP client, on the Pro and Enterprise plans.

## Overview

The **GetMyMFA API** is designed to simplify the process of managing Multi-Factor Authentication (MFA) during end-to-end (E2E) tests. By using this API, you can bypass complex back-end modifications while still simulating real-world MFA flows. Key features of the GetMyMFA API include:

- **Programmatic API Access:** Retrieve MFA codes directly from your application environment without any manual intervention.
- **Self-Service Key Management:** Easily create, rotate, and manage your API keys through a self-service portal.
- **Comprehensive Documentation:** Access Postman collections and Swaggers to streamline integration.

## How It Works

Integrating the GetMyMFA API into your CI/CD or test automation workflow offers several benefits:

- **Simplifies Test Automation:** The API allows you to seamlessly retrieve MFA codes programmatically, eliminating the need for manual intervention and reducing test complexity.
- **Enhances Security:** Automate MFA processes without exposing sensitive data or modifying backend systems, maintaining high security standards throughout your development pipeline.
- **Improves Efficiency:** By automating the retrieval and handling of MFA codes, you can accelerate your test cycles and ensure consistent results, leading to faster deployment times.

By leveraging the **GetMyMFA API**, you can streamline your **CI/CD pipeline**, reduce overhead, and maintain robust security practices, all while delivering a seamless experience for your development and testing teams.

## Frequently Asked Questions

### How does the GetMyMFA API retrieve MFA codes programmatically?

The GetMyMFA API exposes a REST endpoint at /v1/{phoneId}/mfa/latest that returns the most recent MFA code received by your virtual phone number. Call it with your API key in the x-api-key header, and the response includes the mfaCode field with the verification code. It is designed for real-time test automation.

### Can I run parallel tests with different MFA codes?

Yes. Purchase multiple virtual phone numbers and assign one to each parallel test worker. Each number receives its own MFA codes independently, so there are no collisions between concurrent test runs. This works with any parallel execution setup, including Playwright sharding, Cypress parallelization, and Selenium Grid.

### Is there a rate limit on the GetMyMFA API?

The Pro plan supports up to 60 requests per minute per API key, which covers most test automation needs. The Enterprise plan offers higher rate limits and dedicated support for high-volume testing scenarios. Contact us at hello@mymfa.io if you need custom rate limits.

### How do I handle MFA code timing in automated tests?

SMS codes typically arrive within 2-5 seconds. In your test, add a short wait (3-5 seconds) after triggering the MFA flow before calling the GetMyMFA API. For TOTP codes, there is no delay since they are generated instantly. If you need retry logic, poll the API endpoint every 2 seconds until a fresh code appears.

## Code samples

### Sign in with SMS 2FA using GetMyMFA (Playwright)

Minimal Playwright test that logs in, fetches the latest MFA code from GET /v1/{phoneId}/mfa/latest with an x-api-key header, and submits it.

```ts
import { test, expect } from '@playwright/test';

const GMM = 'https://api.get.mymfa.io/v1';

test('signs in with SMS 2FA', async ({ page, request }) => {
  await page.goto('/login');
  await page.fill('#email', 'qa@acme.app');
  await page.fill('#password', process.env.QA_PASSWORD!);
  await page.click('text=Continue');

  // Pull the code that just landed on our private number
  const res = await request.get(`${GMM}/${process.env.GMM_PHONE_ID}/mfa/latest`, {
    headers: { 'x-api-key': process.env.GMM_API_KEY! },
  });
  const { mfaCode } = await res.json();

  await page.fill('#otp', mfaCode);
  await expect(page).toHaveURL('/dashboard');
});
```

### Sign in with SMS 2FA using GetMyMFA (Cypress)

Minimal Cypress test that logs in, fetches the latest MFA code from GET /v1/{phoneId}/mfa/latest with an x-api-key header, and submits it.

```js
const GMM = 'https://api.get.mymfa.io/v1';

it('signs in with SMS 2FA', () => {
  cy.visit('/login');
  cy.get('#email').type('qa@acme.app');
  cy.get('#password').type(Cypress.env('QA_PASSWORD'));
  cy.contains('Continue').click();

  // Pull the code that just landed on our private number
  cy.request({
    url: `${GMM}/${Cypress.env('GMM_PHONE_ID')}/mfa/latest`,
    headers: { 'x-api-key': Cypress.env('GMM_API_KEY') },
  }).then(({ body }) => {
    cy.get('#otp').type(body.mfaCode);
  });

  cy.url().should('include', '/dashboard');
});
```

### Sign in with SMS 2FA using GetMyMFA (Selenium)

Minimal Selenium test that logs in, fetches the latest MFA code from GET /v1/{phoneId}/mfa/latest with an x-api-key header, and submits it.

```python
import os, requests
from selenium.webdriver.common.by import By

GMM = "https://api.get.mymfa.io/v1"

driver.get("https://app.acme.app/login")
driver.find_element(By.ID, "email").send_keys("qa@acme.app")
driver.find_element(By.ID, "password").send_keys(os.environ["QA_PASSWORD"])
driver.find_element(By.XPATH, "//button[text()='Continue']").click()

# Pull the code that just landed on our private number
code = requests.get(
    f"{GMM}/{os.environ['GMM_PHONE_ID']}/mfa/latest",
    headers={"x-api-key": os.environ["GMM_API_KEY"]},
).json()["mfaCode"]

driver.find_element(By.ID, "otp").send_keys(code)
assert "/dashboard" in driver.current_url
```

---

GetMyMFA: https://get.mymfa.io. Machine-readable index: https://get.mymfa.io/llms.txt
