Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developer.prove.com/llms.txt

Use this file to discover all available pages before exploring further.

The following endpoints apply to this flow:

Prerequisites

Implement Prove Pre-Fill

1

Prompt Customer

Create or update your first screen to prompt for phone number and challenge data.
Challenge Page user interface example
Page Summary Language: Let’s Begin by Finding Your Information
Page Summary Description: We can prefill some of this request like your name, address, and contact info for you.
Challenge Page phone number entry example
The table outlines your options for prompting the challenge data.
Contracted SolutionCustomer Prompt Language RequirementsRequired Challenge Data
Prove Pre-FillCustomer can choose one from the following prompts:
“Last 4 SSN/ITIN”
“SSN/ITIN”
“MM/DD/YYYY”
“MM/YYYY”
“MM/DD”
Last 4 SSN/ITIN
Full SSN*
Full DOB
DOB - Month and Year
DOB - Month and Day
*If the customer is applying to open a demand deposit account (DDA), the customer must enter their full social security number (SSN) for the challenge
Prove Pre-Fill with KYC”Full SSN/ITIN”Full SSN
If the customer doesn’t have a mobile number, exit the Prove flow and present a manual app. Customers without a mobile number still have a path forward to continue with their app.
2

Determine Type of Flow

You can decide if the customer is on a mobile or desktop browser using this example. If the isMobile is true, set mobile as the flowType for the Start() function on the server, otherwise you can set desktop:
// Check if the customer is on a mobile or desktop browser.
const authCheck = new proveAuth.AuthenticatorBuilder().build();
let isMobile = authCheck.isMobileWeb()
3

Initialize the Flow

Send a request to your back end server with the phone number, flow type, and an optional challenge to start the flow. This can either be the date of birth or last four digits of the social security number.
async function initialize(phoneNumber, ssn, flowType) {
  const response = await fetch(backendUrl + "/initialize", {
    method: "POST",
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      phoneNumber: phoneNumber,
      "Content-Type": "application/json",
      ssn: ssn
    }),
  });

  const rsp = await response.json();
  const authToken = rsp.authToken;

  return authToken;
}
4

Call the Start Endpoint

On the back end, start a Prove flow with Start() (POST /v3/start lists required fields such as flowType, optional finalTargetUrl for desktop Instant Link, optional ssn and dob for challenge data, allowOTPRetry, and the full response).
For OTP retries (allowOTPRetry), implement the client SDK changes in the next step.
ctx := context.TODO()

rspStart, err := client.V3.V3StartRequest(ctx, &components.V3StartRequest{
	FlowType:       "desktop",
	FinalTargetURL: provesdkservergo.String("https://prove.com"),
	PhoneNumber:    provesdkservergo.String("2001001686"),
	Ssn:            provesdkservergo.String("8370"),
})
if err != nil {
	t.Fatal(err)
}
Return the authToken to the client for Authenticate(). Persist correlationId in the session and pass it to Validate(), Challenge(), and Complete() for this flow. See POST /v3/start for all response fields, JWT behavior, and session timing.
5

Authenticate

Once you have the authToken, build the authenticator for both the mobile and desktop flows.
async function authenticate(isMobileWeb, authToken) {
  // Set up the authenticator for either mobile or desktop flow.
  let builder = new proveAuth.AuthenticatorBuilder();

  if (isMobileWeb) {
    // Set up Mobile Auth and OTP.
    builder = builder
      .withAuthFinishStep((input) => verify(input.authId))
      .withMobileAuthImplementation("fetch")
      .withOtpFallback(otpStart, otpFinish);
  } else {
    // Set up Instant Link.
    builder = builder
      .withAuthFinishStep((input) => verify(input.authId))
      .withInstantLinkFallback(instantLink)
      .withRole("secondary");
  }

  const authenticator = builder.build();

  // Authenticate with the authToken.
  return authenticator.authenticate(authToken);
}

Configure OTP

Use this section to configure SMS OTP fallback in the Web SDK: wire OtpStartStep and OtpFinishStep so the SDK can send the code, collect the PIN, and optionally support resend, OTP retry, or phone-number change.

Prerequisites

  • After Prove sends the SMS, the customer has about two minutes to enter the OTP before the session times out.
  • When building the authenticator, call withOtpFallback(startStep: OtpStartStep | OtpStartStepFn, finishStep: OtpFinishStep | OtpFinishStepFn) and implement both OtpStartStep and OtpFinishStep. Return the phone number from your start step as an object with a phoneNumber field passed to resolve(...); use reject('message') when collection fails. The Prove client SDK orchestrates when each step runs—do not duplicate that orchestration in app code (see Invalid OTP and step orchestration below).
Invalid OTP and step orchestrationWhen the customer enters an invalid OTP, the Prove client SDK detects it and may surface activity related to AuthFinishStep that looks unexpected. This behavior is expected.Do not add your own extra invocation of the OTP finish step to pass the error in otpError. The SDK runs your OtpFinishStep when retry or error UI is needed.Implement the required step functions, but let the Prove client SDK orchestrate when each step runs.

Configure the client

1

Implement start and finish for your use case

Open the tab that matches how the phone number is collected and which OTP options you need.
Use this path when the server already has the phone number (for example from POST /v3/start or your server Start wrapper) and the browser must not prompt for it again.Call resolve(null) (or the equivalent in your snippet) so the SDK knows the customer agreed to receive the SMS. Follow the sample for the exact resolve shape your SDK version expects.
function otpStartStep(phoneNumberNeeded, phoneValidationError) {
  return new Promise((resolve, reject) => {
    // Since no phone number is needed, don't prompt the user.
    resolve(null);
  });
}
Call reject('some error message') if something prevents sending the SMS or completing the flow (for example the customer cancels or leaves the UI with the back button).In the finish step, return the OTP through resolve(result: OtpFinishResult) with the OnSuccess result type and the value wrapped in OtpFinishInput, as in the snippet below.
function otpFinishStep(otpError) {
  return new Promise((resolve, reject) => {
    // If error message is found, handle it.
    if (otpError) {
      // Set to a variable and display it in a field.
      // In this example, we don't do anything with the error.
      var someErrorMessage = otpError.message;
    }

    // Prompt the user for whether they received the SMS.
    // Typically, this is a page that shows the OTP already. We are simplifying
    // it by requiring an input.
    var input = confirm('Did you receive a text message?');
    if (!input) {
      // Close the modal if a text message was not received.
      return;
    }

    // Prompt the user for the OTP.
    var otp = prompt('Enter OTP code:');
    if (otp) {
      // If the input is valid and the user clicked `OK`, return the OTP.
      resolve({
        input: { otp }, // OTP value
        resultType: 0, // OnSuccess enum type = 0
      });
    } else {
      // Else, exit the flow.
      reject('phone invalid or user cancelled');
    }
  });
}
2

Verify the integration

In Sandbox, walk each shipped path (default, prompt, resend, retry if enabled, phone change if enabled). Confirm SMS delivery, OTP entry within the timeout, and that you never stack extra OtpFinishStep invocations on top of the SDK’s invalid-OTP handling—the SDK should remain the single orchestrator for retries and errors.
Use this section to configure the Web SDK so Instant Link SMS can be sent from the browser flow and optional resend or phone-number change behaves as expected.
Instant Link for mobile web isn’t supported.
Custom or vanity Instant Links aren’t supported. You can’t substitute a custom link for the default Instant Link.

Prerequisites

  • Integrate on desktop (or other supported) web; see the callout above for mobile web.
When building the authenticator, use withInstantLinkFallback(startStep: InstantLinkStartStep | InstantLinkStartStepFn, retryStep?: InstantLinkRetryStep | InstantLinkRetryStepFn). Implement InstantLinkStartStep in every flow. Add InstantLinkRetryStep only if you support Resend or Phone Number Change (see those tabs). Return the phone number from your step as an object with a phoneNumber field passed to resolve(...); use reject('message') when collection fails.

Configure the client

1

Implement the Instant Link start and optional retry

Open the tab that matches how the phone number is collected and sent to Prove.
Use this path when the server already has the phone number (for example from POST /v3/start or your server Start wrapper) and the browser must not prompt again.Call resolve(null) (or the equivalent in your snippet) so the SDK knows the customer agreed to receive the SMS. Follow the sample for the exact resolve shape your SDK version expects.
function instantLinkStartStep(phoneNumberNeeded, phoneValidationError) {
  return new Promise((resolve, reject) => {
    // Since no phone number is needed, don't prompt the user.
    resolve(null);
  });
}
2

Verify the integration

In Sandbox, run through each path you ship (default, prompt, and any retry flows). Confirm the SMS sends, the customer can complete the link within the timeout window, and resolve / reject match the UX you expect when the customer cancels or retries.

OTP

OTP entry screen example

Page summary

FlowPage Summary Language
MobileEnter verification code. Please enter the code we just sent to (XXX) XXX-XXXX.
Instant Link screen example

Page summary

FlowPage Summary Language
DesktopCheck your Phone. A text message with a link was just sent to the phone ending in XXXX (last 4 digits of mobile number).

Alternate path for customers

If the customer can’t authenticate through Instant Link or SMS one-time password (OTP), customer exits the Prove flow. Present a manual app as an alternate method of verification.In the desktop flow, a WebSocket opens for 5 minutes on the desktop browser while waiting for the customer to select the link in the text message. Once clicked, the WebSocket closes and the AuthFinishStep function finishes.
If you’re using Content Security Policy headers, ensure you allow connect-src for wss://*.prove-auth.proveapis.com.
6

Verify Mobile Number

In the AuthFinishStep, specify a function to call once the possession checks complete on the mobile phone. This endpoint on your back end server calls the Validate() function to validate the phone number. If it was successful, the server returns the results from the Challenge() function including customer information. Refer to the following example fields that return and then prefill on a form for the customer to verify. The AuthFinishStep then completes. If the user cancels the flow, the server makes a call to the Validate() function and returns success=false.
// Send a verify request to get return customer information.
async function verify() {
  const response = await fetch(backendUrl + "/verify", {
    method: "POST",
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({}),
  });

  const results = await response.json();

  const firstName = document.getElementById("firstNameInput");
  const lastName = document.getElementById("lastNameInput");

  firstName.value = rsp.firstName;
  lastName.value = rsp.lastName;

  return null;
}
7

Validate Mobile Phone

Once the possession checks finish on the mobile device, the finish handler on the client-side SDK executes. You then make a request to your server such as POST /verify to make the next call in the flow to the Validate() function.
You must complete the SDK possession check before calling /validate. If you call /validate immediately after /start without completing the Mobile Auth or OTP flow through the client-side SDK, you will receive error code 9100: Phone possession incomplete. The authToken returned from /start must be passed to the SDK’s authenticate() method, and the possession flow must complete before your backend calls /validate.
Mobile Number Collection Page screenshot

Page summary requirements

Page Summary Language: Let’s Get Started
Page Summary Description: Please enter your phone number to begin the account creation process.

Data entry prompt requirements

Prompt for the mobile number within the input field.

Opt out

Allow customers to select “I don’t have a mobile number” which sends the customer to a manual form to allow customers without mobile numbers to still apply.This function requires the Correlation ID that the Start() function returns.
rspValidate, err := client.V3.V3ValidateRequest(context.TODO(), &components.V3ValidateRequest{
	CorrelationID: rspStart.V3StartResponse.CorrelationID,
})
if err != nil {
    return fmt.Errorf("error on Validate(): %w", err)
}
When success is true, return the prefilled customer information to the front end. See POST /v3/challenge for the full response schema.
8

Verify the Customer Information

Example display of required fields and masking for personal information

Display fields and requirements

Required Display FieldDisplay RequirementsEditable Field
First NameYes - unmaskedYes
Last NameYes - unmaskedYes
AddressYes - unmaskedYes
Extended AddressYes - unmaskedYes
CityYes - unmaskedYes
StateYes - unmaskedYes
Postal CodeYes - unmaskedYes
Phone NumberYes - unmaskedNo
Social Security Number (SSN)Mask first five, display last fourYes*
Date of BirthYes - MM/DD/YYYYYes**
* Upon edit, clear data and require customer to enter full SSN.
**Upon edit, clear the data and require customer to enter the full date of birth.
Required Display FieldDisplay RequirementsEditable Field
First NameYes - unmaskedYes
Last NameYes - unmaskedYes
AddressYes - unmaskedYes
Extended AddressYes - unmaskedYes
CityYes - unmaskedYes
StateYes - unmaskedYes
Postal CodeYes - unmaskedYes
Phone NumberYes - unmaskedNo
Social Security NumberMask first five, display last fourNo, full SSN entered at beginning of process.
Date of BirthYes - MM/DD/YYYYYes*
* Upon edit, clear the data and require customer to enter the full date of birth.
Know Your Customer (KYC) Required Customer ConfirmationInclude this statement before the submit button. You can include an optional checkbox.“I have reviewed the information provided and confirm it’s accurate.”
Once the customer has made any edits to their prefill information, submit that information to the back end server so the Complete() call can then verify the customer information.
// Send request to the backend to verify customer information.
async function sendInfo(firstName, lastName) {
  const response = await fetch(backendUrl + "/finish", {
    method: "POST",
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      firstName: firstName,
      lastName: lastName,
    }),
  });
  const results = await response.json();
  const rsp = JSON.stringify(results);

  return rsp;
}
9

Call the Complete Endpoint

This is the final server call that verifies customer information against the possession-validated phone. Call Complete() with the correlation ID from Start() and your individual payload (POST /v3/complete).
For the KYC add-on, include the attributes needed to return KYC and CIP (for example name, DOB, SSN or address). Reason codes, example responses, and field definitions are documented on POST /v3/complete.
rspComplete, err := client.V3.V3CompleteRequest(context.TODO(), &components.V3CompleteRequest{
	CorrelationID: rspStart.V3StartResponse.CorrelationID,
	Individual: components.Individual{
		FirstName: provesdkservergo.String("Tod"),
		LastName:  provesdkservergo.String("Weedall"),
		Addresses: []components.AddressEntry{
			{
				Address:    provesdkservergo.String("39 South Trail"),
				City:       provesdkservergo.String("San Antonio"),
				Region:     provesdkservergo.String("TX"),
				PostalCode: provesdkservergo.String("78285"),
			},
		},
		Ssn: provesdkservergo.String("565228370"),
		Dob: provesdkservergo.String("1984-12-10"),
		EmailAddresses: []string{
			"[email protected]",
		},
	},
})
if err != nil {
	return fmt.Errorf("error on Complete(): %w", err)
}
Return the verification outcome to your front end. See POST /v3/complete for success, next, and related fields.