Learn more about the details of the Server-Side SDK.
We provide server SDKs in the following languages: Java, TypeScript/JavaScript, and Go. If your backend language is not currently supported, you can easily interact with our REST APIs.
Installation
Install the server SDK of your choice by running a command in your terminal, or by using a dependency management tool specific to your project.
# The Go library is hosted on GitHub so you can use this command to import it
# to your Go application.
go get github.com/prove-identity/prove-sdk-server-go
# Ensure you import the SDK in your code like this:
import (
provesdkservergo "github.com/prove-identity/prove-sdk-server-go"
"github.com/prove-identity/prove-sdk-server-go/models/components"
)
# Run this command to install package from GitHub and save as a dependency
npm install -S @prove-identity/prove-api
# Import the SDK in your code like this:
import { Proveapi } from "@prove-identity/prove-api";
import { OAuthClient, WithAuthorization } from "@prove-identity/prove-api/sdk/oauth"
# See the latest version number here: https://central.sonatype.com/artifact/com.prove/proveapi
Gradle:
implementation 'com.prove:proveapi:0.10.0'
Maven:
<dependency>
<groupId>com.prove</groupId>
<artifactId>proveapi</artifactId>
<version>0.10.0</version>
</dependency>
Other Backend Languages
We have code samples for how to interact with the API endpoints in many different languages. Browse the API Reference page and click on your language on the right side. If you still don't see your language, click on the 3 vertical circles on the right and you should see a drop down of all the different languages.
OAuth for Authentication
In order to access the Prove API, you'll need to provide your OAuth client ID and client secret. We recommend storing them.
You can load them from environment variables or another method:
// Get environment variables.
clientID := os.Getenv("PROVE_CLIENT_ID")
if len(clientID) == 0 {
return fmt.Errorf("missing env variable: %s", "PROVE_CLIENT_ID")
}
clientSecret := os.Getenv("PROVE_CLIENT_SECRET")
if len(clientSecret) == 0 {
return fmt.Errorf("missing env variable: %s", "PROVE_CLIENT_SECRET")
}
proveEnv := "uat-us" // Use UAT in US region.
// Create client for Prove API.
client := provesdkservergo.New(
provesdkservergo.WithServer(proveEnv),
provesdkservergo.WithSecurity(components.Security{
ClientID: provesdkservergo.String(clientID),
ClientSecret: provesdkservergo.String(clientSecret),
}),
)
// Get OAuth credentials from environment variables.
const oauthClientId = process.env.PROVE_CLIENT_ID;
const oauthClientSecret = process.env.PROVE_CLIENT_SECRET;
const proveEnv = "uat-us" // Use UAT in US region.
// Create client for the Prove API.
const sdk = new ProveAPI({
server: proveEnv,
security: {
clientID: oauthClientId,
clientSecret: oauthClientSecret,
},
});
// Create client for Prove API.
Proveapi sdk = Proveapi.builder()
.security(Security.builder()
.server(Proveapi.AvailableServers.UAT_US)
.clientID("<YOUR_CLIENT_ID_HERE>")
.clientSecret("<YOUR_CLIENT_SECRET_HERE>")
.build())
.build();
Token Expiration
The OAuth token will expire after 60 minutes, and a new token will need to be acquired.
Next Field
Each of the functions return a Next
field. This field is a map that tells you which function you need to call next, or in the case of done
, no further calls are needed. These are the possible return values:
v3-validate
:/v3/validate
v3-challenge
:/v3/challenge
v3-complete
:/v3/complete
done
:done
Start()
To start the implementation, add a new endpoint to your server (example: POST /initiate
) so the frontend/client code can submit the flow type, phone number, and challenge (either last 4 of SSN or date of birth). On the backend, you'll start a new Prove flow with a call to the Start()
function. This function takes these required parameters:
- Flow Type: either
desktop
ormobile
to describe which type of device the end user is starting their flow on.
Possession Timeouts
When flow type is
desktop
, Instant Link will be used for the possession check. When flow type ismobile
, first Mobile Auth (if enabled) and then OTP as a fallback. The Instant Link session has a 5 minute timeout from when it's sent via SMS to when the end user can click on the link successfully. The OTP session has a 2 minute timeout from when it's sent via SMS to when the end user can enter in the OTP successfully.
- Final Target URL: only required when
Flow Type=desktop
. It can be either a Prove provided URL or your own URL that instructs the end user to close their mobile browser.
Optionally, one of these parameters can be passed in:
- SSN: full or last 4 digits of the end user's social security number. If passed into
Start()
, then it does not need to be passed intoChallenge()
. - DOB: date of birth in one of these formats: YYYY-MM-DD, YYYY-MM, MM-DD. If passed into
Start()
, then it does not need to be passed intoChallenge()
.
Here is an example:
// Send the start request.
rspStart, err := client.V3.V3StartRequest(context.TODO(), &components.V3StartRequest{
FlowType: "desktop",
FinalTargetURL: provesdkservergo.String("https://www.example.com"),
})
if err != nil {
return fmt.Errorf("error on Start: %w", err)
}
let startReq = {
flowType: 'desktop',
finalTargetUrl: 'https://www.example.com'
}
// Send the start request.
const rspStart = await sdk.v3.v3StartRequest(startReq);
if (!rspStart) {
console.error("Start error.")
return
}
// Send the start request.
V3StartRequest req = V3StartRequest.builder()
.flowType("desktop")
.finalTargetUrl("https://www.example.com")
.build();
// You may want to use the .get() method when working with the response object.
The function returns the following fields:
- Auth Token: send this to your client side code so it can be passed into the Authenticate() function - it's a short lived JWT (authentication token) that is tied to the current flow and used to facilitate the possession checks.
- Correlation ID: save GUID in your current session, it will need to be passed in to each of the
Validate()
,Challenge()
, andComplete()
function calls of the same flow.
The correlation ID allows our system to tie together different system calls for the same Prove flow. It can also be used the troubleshoot so we require it to be passed into each of the request bodies and SDK calls. The session will expire in 15 minutes from when the correlation ID is returned from the Start() call.
- Next: map of the next API you need to call you need to make.
You should then return the auth token in a response to the frontend.
The phone number field is also required in Sandbox so the system knows which scenario you are testing. If you don't pass in the phone number of a valid test user, then it will return an HTTP 400 (8007 - no test user found matching the phone number) error. In production, a phone number is not required in the Start endpoint if you're using Mobile Auth.
Validate()
Once the possession checks are completed on the mobile device, the finish handler on the client SDK will be called and that should make a request to your server (you'll need another new endpoint, for example: POST /verify
) to make the next call in the flow to the Validate() function.
This function takes only this required parameter:
- Correlation ID: this is the ID returned by the Start() function.
Here is an example:
rspValidate, err := client.V3.V3ValidateRequest(context.TODO(), &components.V3ValidateRequest{
CorrelationID: rspStart.V3StartResponse.CorrelationID,
})
if err != nil {
return fmt.Errorf("error on Validate(): %w", err)
}
const rspValidate = await sdk.v3.v3ValidateRequest({
correlationId: rspStart.v3StartResponse?.correlationId || '',
})
if (!rspValidate) {
console.error('Validate error.')
return
}
V3ValidateRequest req = V3ValidateRequest.builder()
.correlationId("713189b8-5555-4b08-83ba-75d08780aebd")
.build();
V3ValidateRequestResponse res = sdk.v3().v3ValidateRequest()
.request(req)
.call();
// You may want to use the .get() method when working with the response object.
The function returns the following fields:
- Success: either
true
if the mobile number validation was successful, orfalse
if it failed. - Challenge Missing: either
true
if the challenge needs to be passed into the Challenge() function, orfalse
if the challenge is not needed. - Phone Number: either the validated phone number or no field.
- Next: map of the next API you need to call you need to make.
The challenge missing field determines if you need to return to the frontend and request an additional user input of either the last 4 of their social security number or date of birth. If the challenge was already passed into the Start() call (challengeMissing=false and next contains v3-challenge), the backend can then make a call to the Challenge() function and return the results to the frontend.
Challenge()
If the Validate() function returns v3-challenge
as one of the keys in the Next
field map, the Challenge() function may be called to return the user information matching the mobile number and challenge.
The Challenge() capability is only available in Prove Pre-Fill®, it's not available in Prove Identity®. You'll notice that when using Prove Identity®, if Validate() is successful, it will then return
v3-complete
as one of the keys in theNext
field map instead ofv3-challenge
.
This function takes has one required parameter:
- Correlation ID: this is the ID returned by the Start() function.
If the Validate() function returned Challenge Missing=true
, one of these parameters are also required:
- SSN: full or last 4 digits of the end user's social security number.
- DOB: date of birth in one of these formats: YYYY-MM-DD, YYYY-MM, MM-DD.
Here is an example:
rspChallenge, err := client.V3.V3ChallengeRequest(context.TODO(), &components.V3ChallengeRequest{
CorrelationID: rspStart.V3StartResponse.CorrelationID,
Dob: provesdkservergo.String("1980-03-15"),
})
if err != nil {
return fmt.Errorf("error on Challenge(): %w", err)
}
const rspChallenge = await sdk.v3.v3ChallengeRequest({
correlationId: rspStart.v3StartResponse?.correlationId || '',
dob: '1980-03-15',
})
if (!rspValidate) {
console.error("Challenge error.")
return
}
V3ChallengeRequest req = V3ChallengeRequest.builder()
.correlationId("713189b8-5555-4b08-83ba-75d08780aebd")
.dob("2024-05-02")
.build();
V3ChallengeRequestResponse res = sdk.v3().v3ChallengeRequest()
.request(req)
.call();
// You may want to use the .get() method when working with the response object.
The function returns the following fields:
- Success: either
true
if the challenge was successful and user info is returned, orfalse
if it failed. - Individual: user information in a map.
- Next: map of the next API you need to call you need to make.
If the success field is true, you should return the user information in a response to the frontend to pre-fill the form.
Complete()
Once the end user reviews their information and makes any edits, they need to submit the user information to the backend (new endpoint example: POST /finish
) for verification.
This function is the final call in the flow that verifies the user information.
This function takes these required parameters:
- Correlation ID: this is the ID returned by the Start() function. It will validate against this RegEx:
^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$
. - Individual: user information in a map.
Here is an example:
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)
}
const rspComplete = await sdk.v3.v3CompleteRequest({
correlationId: rspStart.v3StartResponse?.correlationId || '',
individual: {
firstName: 'Tod',
lastName: 'Weedall',
addresses: [{
address: '39 South Trail',
city: 'San Antonio',
region: 'TX',
postalCode: '78285',
}],
dob: '1984-12-10',
emailAddresses: [
'[email protected]',
],
ssn: '565228370',
},
});
if (!rspComplete) {
console.error("Complete error.")
return
}
V3CompleteRequest req = V3CompleteRequest.builder()
.correlationId("713189b8-5555-4b08-83ba-75d08780aebd")
.individual(V3CompleteIndividualRequest.builder()
.addresses(java.util.List.of(
V3CompleteAddressEntryRequest.builder()
.address("39 South Trail")
.city("San Antonio")
.extendedAddress("Apt 23")
.postalCode("78285")
.region("TX")
.build()))
.dob("2024-05-02T00:00:00Z")
.emailAddresses(java.util.List.of(
"[email protected]",
"[email protected]"))
.firstName("Tod")
.lastName("Weedall")
.ssn("265228370")
.build())
.build();
V3CompleteRequestResponse res = sdk.v3().v3CompleteRequest()
.request(req)
.call();
// You may want to use the .get() method when working with the response object.
The function returns the following fields:
- Success: either
true
if the user information was verified, orfalse
if it failed.- Next: map of the next API you need to call you need to make - this will always have
Done
.You can then respond to the frontend with the results of the user verification.
SDK Updates
Each of our server SDKs are hosted on GitHub. Once you create a free GitHub account, you can Watch any of the projects and you will get a notification when there are new releases.
Below are links to each of the server SDKs: