Run a Geodistance check and a Geocoding check using the API
This developer guide takes you through the steps to run a Geodistance check in the Passfort API 4.0 to confirm whether two coordinates are within the same proximity.
The guide also includes instructions for using the Geocoding check to get the coordinates of the customer's stated address to use in the Geodistance check.
Choose a profile and get the profile ID
The Geodistance check and Geocoding check are always run on profiles with the INDIVIDUAL
entity type.
Choose an individual profile to run the check on, and take note of the profile's ID number, for example, a2c4393a-e219-67a4-5ab4-2186952e9038
). You'll need it to confirm it has the required fields and also to run the check later.
If you haven't created the profile yet, follow the steps to create a profile using the API. If you have access to the full Passfort product, you can also create a profile via the portal. To get the profile ID, view the profile in the portal and copy the string of letters and numbers after /profiles/
in the URL.
Confirm the profile has the required fields
The Geodistance check and Geocoding check are run on the Verify address task (INDIVIDUAL_VERIFY_ADDRESS
).
Geodistance check only
If you're only running the Geodistance check, the profile does not require any additional fields. You can confirm it has the Verify address task by making a request to the following endpoint.
Request endpoint:
GET https://api.passfort.com/4.0/profiles/{profile_id}/tasks
In this example, the only task on the profile is Verify address.
Sample response:
[ { "check_ids": [ ], "creation_date": "2020-08-27 13:48:16", "form_instance_ids": [ ], "id": "72aadb55-8b02-8495-d6b0-e1627ec23612", "is_complete": false, "is_expired": false, "is_skipped": false, "state": "INCOMPLETE", "type": "INDIVIDUAL_VERIFY_ADDRESS", "variant": { "alias": "verify_address", "id": "5562c4e4-4d12-b16a-a151-7c9eed6816e9", "task_type": "INDIVIDUAL_VERIFY_ADDRESS" } } ]
Use the response to:
Confirm the profile has the
INDIVIDUAL_VERIFY_ADDRESS
task.Take note of the task ID (
id
). Use the corresponding task alias (variant.alias
) to confirm you're looking at the right task. If there is more than one task with the same alias, which happens when a task has more than one version, use the task with"is_expired": "false"
. Note that the task variant ID (variant.id
) won't be used to run this check, so you don't need to take note of it.
Geodistance check and geocoding check
If, in addition to the Geodistance check, you want to run the Geocoding check to get the latitude and longitude of the customer's stated address, you have two options:
You can send the stated address in the request to run the Geocoding check.
You can run the Geocoding check without an address, which retrieves the latitude and longitude for the address in the profile's
collected_data
.
If you're sending the stated address in the request to run the Geocoding check, the profile only needs to have the Verify address task. Use the preceding endpoint to confirm if the task is present.
If you want to use the address in the profile's collected_data
, you can confirm it's there as well as confirm the profile has the Verify address task by making a single call to the following endpoint.
Request endpoint:
GET https://api.passfort.com/4.0/profiles/{profile_id}/tasks
In this example, data is returned for an individual profile with an address and the Verify address task.
Sample response:
{ "applications": [ … ], "category": "APPLICANT", "checks": [ ], "collected_data": { "entity_type": "INDIVIDUAL", "address_history": [ { "address": { "type": "STRUCTURED", "country": "GBR", "locality": "London", "original_freeform_address": "38, Crown Street, London, W1 2ZT", "original_structured_address": { … }, "postal_code": "W1 2ZT", "route": "Crown Street", "street_number": "38" } } ], "personal_details": { … } }, "collection_steps": [ ], "creation_date": "2020-08-27 12:50:07", "display_name": "Alex Wheeler", "document_images": [ ], "events": [ ], "has_associates": false, "has_collection_steps": false, "id": "a2c4393a-e219-67a4-5ab4-2186952e9038", "linked_to": [ ], "role": "INDIVIDUAL_CUSTOMER", "root_id": "6bba3592-d9de-1ee5-8e97-ba8d8d13c558", "status": "NORMAL", "tags": [ ], "task_progress": { … }, "task_types": [ "INDIVIDUAL_VERIFY_ADDRESS" ], "tasks": [ { "check_ids": [ ], "creation_date": "2020-08-27 12:50:07", "form_instance_ids": [ ], "id": "3d7a333c-418d-72a1-007b-06854dbb28eb", "is_complete": false, "is_expired": false, "is_skipped": false, "state": "INCOMPLETE", "type": "INDIVIDUAL_VERIFY_ADDRESS", "variant": { "alias": "fraud_check_individuals", "id": "ddc72ea7-6e45-cc3b-dc52-30a94b9ec8c2", "task_type": "INDIVIDUAL_VERIFY_ADDRESS" } } ], "unresolved_event_types": [ ] }
Use the response to:
Confirm the profile has the
INDIVIDUAL_VERIFY_ADDRESS
task.Take note of the task ID, or
tasks.id
. Use the corresponding task alias (tasks.variant.alias
) to confirm you're looking at the right task. If there is more than one task with the same alias, which happens when a task has more than one version, use the task with"is_expired": "false"
. Note that the task variant ID (tasks.variant.id
) won't be used to run this check, so you don't need to take note of it.Confirm the profile has an address (
collected_data.address_history.address
).
If the individual has multiple addresses, the most recent address is used. If no dates are provided, the address is selected at random. To add an address to the profile's collected_data
, follow the steps to update Passfort's profile data.
Get the coordinates of the customer's stated address
To run the check, you'll need the latitude and longitude of the customer's stated address.
If you have this information, you can skip the next section.
If not, you can use the Geocoding check to get the latitude and longitude.
Run the Geocoding check
To get the latitude and longitude of the address in the profile using the Geocoding check, make the following request.
Request endpoint:
POST https://api.passfort.com/4.0/profiles/{profile_id}/checks
By default, the Geocoding check runs asynchronously.
You can also send mode
as a query parameter to run the check asynchronously.
Body parameters:
When you make the POST
request, include the following parameters in the body.
Key | Value | Description |
*Required string |
| The type of check that's being run. |
Optional, but we recommend including it whenever possible string | Sample value: | When you're running the check on an individual profile, this is the unique identifier for the |
*Required object | For a sample value, see the following sample request body. | Object to indicate which variant of the check will run. |
*Required string This key is optional if | Sample value: | The check alias. |
*Required string This key is optional if | Sample value:
| The unique identifier for the check. |
Optional object | For a sample value, see the following sample request body. | Object containing the address. If you do not send an address in the request, the address from the profile is used. |
*Required string |
| The address type. Note that freeform addresses cannot be used to run this check. Learn how to convert a freeform address to a structured address. |
*Required string | Sample value: The country must be provided as an ISO3 code. | The country of the address. |
Optional string | Sample value: | The county of the address. Note that a US state or a Canadian province or territory should not go here. |
Optional string | Sample value: | The city or town of the address. |
Optional string | Sample value:
| The freeform address, prior to structuring attempts. |
Optional string | Sample value: | The postal code or zip code of the address. |
Optional string | Sample value: | The postal town or district of the address. |
Optional string | Sample value: | The name of the building. |
Optional string | Sample value: | The name of the route or street. |
*Required (US, Canada, Australia) Optional for all other countries string | Sample value: | The state, province, or territory of the address. The format follows the state code of the ISO-3166-2 standard. Note that a UK county should not go here. |
Optional string | Sample value: | The street number of the address. |
Optional string | Sample value: | The subaddress within the building. Typically this is a flat number. |
Sample request body:
{ "check_type": "GEOCODING", "task_ids": [ "3d7a333c-418d-72a1-007b-06854dbb28eb" ], "variant": { "alias": "default" }, "address": { "type": "STRUCTURED", "country": "GBR", "locality": "London", "original_freeform_address": "38, Crown Street, London, W1 2ZT", "postal_code": "W1 2ZT", "route": "Crown Street", "street_number": "38" } }
Sample response:
{ "address": { "country": "GBR", "locality": "London", "original_freeform_address": "38, Crown Street, London, W1 2ZT", "original_structured_address": { "country": "GBR", "locality": "London", "postal_code": "W1 2ZT", "route": "Crown Street", "street_number": "38" }, "postal_code": "W1 2ZT", "route": "Crown Street", "street_number": "38", "type": "STRUCTURED" }, "check_type": "GEOCODING", "id": "72aadb55-8b02-8495-d6b0-e1627ec23612", "instructed_on": "2020-08-27 13:52:25", "performed_on": "2020-08-27 13:52:25", "providers": [], "state": "PENDING", "task_ids": [ "3d7a333c-418d-72a1-007b-06854dbb28eb" ], "variant": { ... } }
Take note of the check id
in the response because you'll need it for the next sections to learn how to get the check results.
Because this check runs asynchronously, the check state
is expected to be PENDING
in the response.
Get the check result
Listen to the Check completed webhook to get a notification when the check is finished running and to learn what the result is.
This webhook sends a payload whenever results are returned from any check, including checks other than the Geocoding check.
Payloads from this webhook have several important keys:
secret
: Authenticate the request by ensuring this secret matches your secret.data.check.id
: The check ID. Use it to confirm the payload is for your check by matching it to the check ID you captured in the previous step.data.check.check_type
: The type of check was run. When the Geocoding check is run, the value isGEOCODING
.data.check.variant.alias
: The alias for the check variant. You can use it for additional confirmation that the payload is for your check by matching it to the check variant alias you captured in the previous step.data.check.result
: The results of the check. Possible results for the Geocoding check arePass
,Fail
, orError
. If the coordinates are found, the result isPass
. If the coordinates cannot be found, the result isFail
.
In this example, the Geocoding check was able to find the latitude and longitude, which we know because the result
is Pass
.
{ "id": "33bae6b8-5689-b96b-143c-06e93ab8527e", "event": "CHECK_COMPLETED", "secret": "yourSecret", "timestamp": 1570807808, "data": { "check": { "check_type": "GEOCODING", "id": "72aadb55-8b02-8495-d6b0-e1627ec23612", "result": "Pass", "variant": { "alias": geocoding", "id": "ea565b55-47d9-1858-4588-3a22a3838707", "name": "Geocoding" } }, "customer_ref": null, "profile_id": "a2c4393a-e219-67a4-5ab4-2186952e9038" } }
Get more information about the check result
To get the latitude and longitude of the address, make a call to the following endpoint.
In the request, include the profile ID and the check ID.
Request endpoint:
GET https://api.passfort.com/4.0/profiles/{profile_id}/checks/{check_id}
Sample response:
{ "address": { "country": "GBR", "locality": "London", "original_freeform_address": "38, Crown Street, London, W1 2ZT", "original_structured_address": { "country": "GBR", "locality": "London", "postal_code": "W1 2ZT", "route": "Crown Street", "street_number": "38" }, "postal_code": "W1 2ZT", "route": "Crown Street", "street_number": "38", "type": "STRUCTURED" }, "check_type": "GEOCODING", "completed_on": "2020-08-27 13:52:25", "decision": "PASS", "errors": [], "id": "d526831a-e2f2-11ea-ab2b-1e271aa31109", "input_data": { "address_history": [ … ], "entity_type": "INDIVIDUAL" }, "instructed_on": "2020-08-27 13:52:25", "output_data": { "address_history": [ { "address": { "country": "GBR", "latitude": 57.145618, "locality": "London", "longitude": -2.096897, "original_freeform_address": "Crown Street, London, W1 2ZT", "original_structured_address": { "country": "GBR", "latitude": 57.145618, "locality": "London", "longitude": -2.096897, "postal_code": "W1 2ZT", "route": "Crown Street" }, "postal_code": "W1 2ZT", "route": "Crown Street", "street_number": "", "type": "STRUCTURED" } } ], "entity_type": "INDIVIDUAL" }, "performed_on": "2020-08-27 13:52:25", "providers": [ … ], "result": "Pass", "started_on": "2020-08-27 13:52:25", "state": "COMPLETE", "task_ids": [ "692e8682-e239-11ea-9218-5a65e6bcfda0" ], "variant": { "id": "631897c2-e179-11ea-ba0a-5694cb8533a6", "name": "Geocoding" } }
Capture the latitude (output_data.address_history.address.latitude
) and the longitude (output_data.address_history.address.latitude
) so you have it when you run the Geodistance check.
Get the coordinates of the user's current location
To run the Geodistance check, you'll also need the latitude and longitude of the user's current location.
Once you have this information, you can go to the step to run the Geolocation check.
You can use the Device fraud detection check with TransUnion TruValidate to get the coordinates of the user's device. To do so, follow the steps to run a Device fraud detection check. When you get more information about the check result, the latitude and longitude are returned in the output_data.ip_location.coordinates
object.
Run the Geodistance check
To run the Geodistance check, make a request to the following endpoint.
Request endpoint:
POST https://api.passfort.com/4.0/profiles/{profile_id}/checks
By default, the Geodistance check runs asynchronously, but you can send mode as a query parameter to run the check synchronously.
Body parameters:
When you make the POST
request, include the following parameters in the body.
Key | Value | Description |
*Required string |
| The type of check that's being run. |
Optional, but we recommend including it whenever possible string | Sample value: | When you're running the check on an individual profile, this is the unique identifier for the |
*Required object | For a sample value, see the following sample request body. | Object to indicate which variant of the check will run. |
*Required string This key is optional if | Sample value: | The check alias. |
*Required string This key is optional if | Sample value: | The unique identifier for the check. |
*Required object | For a sample value, see the following sample request body. | Object with the coordinates for the stated address and current location. |
*Required object | For a sample value, see the following sample request body. | Object with the latitude and longitude of the stated address. |
Optional string | Sample value: | The name of the first coordinate. If you do not send a name, this coordinate will be named Initial point. |
*Required float | Sample value: | Latitude of the stated address. |
*Required Float | Sample value: | Longitude of the stated address. |
*Required Object | For a sample value, see the following sample request body. | Object with the latitude and longitude of the current address. |
Optional string | Sample value: | The name of the second coordinate. If you do not send a name, this coordinate will be named Final point. |
*Required float | Sample value: | Latitude of the current address. |
*Required float | Sample value: | Longitude of the current address. |
Sample request body:
{ "check_type":"GEODISTANCE", "task_ids": [ "3d7a333c-418d-72a1-007b-06854dbb28eb" ], "variant": { "alias": "default" }, "coordinates": { "p1": { "name": "Stated address", "latitude": 53.38297, "longitude": -1.4659 }, "p2": { "name": "Current location", "latitude": 51.50853, "longitude": -0.12574 } } }
Sample response:
{ "check_type": "GEODISTANCE", "coordinates": { "p1": { "name": "Stated address", "latitude": 53.38297, "longitude": -1.4659 }, "p2": { "name": "Current location", "latitude": 51.50853, "longitude": -0.12574 } }, "id": "72aadb55-8b02-8495-d6b0-e1627ec23612", "instructed_on": "2020-08-27 13:53:12", "performed_on": "2020-08-27 13:53:12", "providers": [ ], "state": "PENDING", "task_ids": [ "3d7a333c-418d-72a1-007b-06854dbb28eb0" ], "variant": { … } }
Take note of the check id
in the response because you'll need it for the sections to learn how to get the check results.
Because this check runs asynchronously, the check state
is expected to be PENDING
in the response.
Get the check result
Listen to the Check completed webhook to get a notification when the check is finished running and to learn what the result is.
This webhook sends a payload whenever results are returned from any check, including checks other than the Geodistance check.
Payloads from this webhook have several important keys:
secret
: Authenticate the request by ensuring this secret matches your secret.data.check.id
: The check ID. Use it to confirm the payload is for your check by matching it to the check ID you captured in the previous step.data.check.check_type
: The type of check was run. When the Geodistance check is run, the value is GEODISTANCE.data.check.variant.alias
: The alias for the check variant. You can use it for additional confirmation that the payload is for your check by matching it to the check variant alias you captured in the previous step.data.check.result
: The results of the check. Possible results for the Geodistance check are Pass, Fail, or Error. If the distance between the two coordinates is within the proximity threshold configured for the task, the result is Pass. If the distance is beyond the threshold or the coordinates are not provided, the result is Fail.
In this example, the Geodistance check failed.
{ "id": "33bae6b8-5689-b96b-143c-06e93ab8527e", "event": "CHECK_COMPLETED", "secret": "yourSecret", "timestamp": 1570807808, "data": { "check": { "check_type": "GEODISTANCE", "id": "72aadb55-8b02-8495-d6b0-e1627ec23612", "result": "Fail", "variant": { "alias": "geodistance", "id": "ea565b55-47d9-1858-4588-3a22a3838707", "name": "Geodistance" } }, "customer_ref": null, "profile_id": "a2c4393a-e219-67a4-5ab4-2186952e9038" } }
Get more information about the check result
To get more information about the result, make a call to the following endpoint.
In the request, include the profile ID and the check ID.
Request endpoint:
GET https://api.passfort.com/4.0/profiles/{profile_id}/checks/{check_id}
Sample response:
{ "check_type": "GEODISTANCE", "completed_on": "2020-08-27 13:53:23", "coordinates": { "p1": { "latitude": 53.38297, "longitude": -1.4659, "name": "Stated IP" }, "p2": { "latitude": 51.50853, "longitude": -0.12574, "name": "Current location" } }, "decision": "FAIL", "errors": [ ], "id": "d526831a-e2f2-11ea-ab2b-1e271aa31109", "input_data": { "contact_details": { }, "coordinates": { "p1": { "latitude": 53.38297, "longitude": -1.4659, "name": "Stated IP" }, "p2": { "latitude": 51.50853, "longitude": -0.12574, "name": "Current location" } }, "entity_type": "INDIVIDUAL", "personal_details": { "name": { "family_name": "Wheeler", "given_names": [ "Alex" ] } } }, "instructed_on": "2020-08-27 13:53:12", "output_data": { "entity_type": "INDIVIDUAL", "geodistance": { "distance": 227.605138, "is_within_threshold": false, "threshold": 100.0 } }, "performed_on": "2020-08-27 13:53:12", "providers": [ { "instructed_on": "2020-08-27 13:53:12", "provider_name": "GeoDistance Passfort", "variant_name": "Passfort" } ], "result": "Fail", "started_on": "2020-08-27 13:53:12", "state": "COMPLETE", "task_ids": [ "692e8682-e239-11ea-9218-5a65e6bcfda0" ], "variant": { "id": "4371c34c-e17d-11ea-8479-d6de177101d7", "name": "Geodistance" } }
Use the response to:
Confirm whether the distance is within the threshold. If it is,
output_data.geodistance.is_within_threshold
istrue
.See the threshold configured for the task (
output_data.geodistance.threshold
).See the distance between the two points, in kilometres (
output_data.geodistance.distance
).
The result returns the distance in kilometres, but portal users will see the distance in miles. The distance is measured as a direct path between the two points. It does not account for any mountains, rivers, and so on.