> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# Location Verification Warnings & LOCATION_ Codes

> Every LOCATION_ warning Didit raises on a location check: geofence, accuracy, spoofing, VPN, distance and permission findings, with trigger and default action.

## Overview

Warnings on the location report flag every condition Didit found on a Location verification step.
They land in the `warnings[]` array of each item of `geolocation_checks[]` (see the [location report](https://docs.didit.me/core-technology/location-verification/report-location-verification.md)).

Every warning has three layers:

1. **The `risk` code**: a stable identifier you can match on, all starting with `LOCATION_`.
2. **The `log_type`**: `information`, `warning` or `error`. For configurable risks it follows the configured action: `NO_ACTION` gives `information`, `REVIEW` gives `warning`, `DECLINE` gives `error`.
3. **The decision impact**: the strongest action among the warnings sets the step `status`. `REVIEW` gives `In Review`, `DECLINE` gives `Declined`, and `NO_ACTION` leaves it untouched.

Uncertainty and refusal default to `REVIEW`, never `DECLINE`: a denied permission, an indoor position or a wide radius is not evidence of fraud.
Warnings about accuracy, freshness, areas, distance and anonymizers are raised only on the last attempt, so a person who succeeds on the second try carries no warning.
Custom `status_rules` on the node can keep or raise the status but never lower it.

## Auto-decline conditions

These always decline the step, with `log_type: "error"`, and have no action key.

| Risk | Trigger |
| - | - |
| `LOCATION_REPLAY_DETECTED` | The submission carried a challenge that belongs to another session. Each attempt gets one single-use challenge bound to its session, so presenting it elsewhere is a replay. |
| `LOCATION_INTEGRITY_FAILED` | A device attestation accompanied the position and failed verification. |

## Warnings produced

Defaults are the actions of a step with no `geolocation_preset`.
Under `licensing`, `LOCATION_VPN_DETECTED`, `LOCATION_TOR_DETECTED` and `LOCATION_EMULATOR_DETECTED` default to `DECLINE` and `LOCATION_PROXY_DETECTED` to `REVIEW`.
Under `fraud_screening`, every default that is `DECLINE` becomes `REVIEW`, and those four anonymizer findings become `REVIEW`.
An action you set explicitly always wins.

### Permission and availability

| Risk | Trigger | Config key | Default |
| - | - | - | - |
| `LOCATION_PERMISSION_DENIED` | The person declined or dismissed the location prompt on every allowed attempt. A choice, not evidence of fraud. | `geolocation_permission_denied_action` | `REVIEW` |
| `LOCATION_RESTRICTED` | The operating system refused before the person could answer: location services are off device-wide, or a device-management or parental-control policy blocks them. | `geolocation_unavailable_action` | `REVIEW` |
| `LOCATION_UNAVAILABLE` | The device accepted the request but its positioning system returned no position on every allowed attempt. Ordinary indoors and underground. | `geolocation_unavailable_action` | `REVIEW` |
| `LOCATION_TIMEOUT` | No position arrived within `geolocation_timeout_seconds` on any allowed attempt. | `geolocation_unavailable_action` | `REVIEW` |
| `LOCATION_SKIPPED` | The workflow allows skipping and the person continued without sharing a location. | `geolocation_unavailable_action` | `REVIEW` |
| `LOCATION_UNSUPPORTED_CLIENT` | The session reached an app or SDK build that does not implement the step. Didit closed the step instead of leaving the session parked. Upgrade the SDK. | `geolocation_unavailable_action` | `REVIEW` |

### Precision and freshness

| Risk | Trigger | Config key | Default |
| - | - | - | - |
| `LOCATION_LOW_ACCURACY` | The best position had a radius wider than `geolocation_max_accuracy_radius_m`. A measure of confidence, not of honesty. | `geolocation_low_accuracy_action` | `REVIEW` |
| `LOCATION_ACCURACY_UNDETERMINED` | The position carried no radius on any allowed attempt, so nothing shows it meets the limit. It never counts as having met it. | `geolocation_low_accuracy_action` | `REVIEW` |
| `LOCATION_STALE_FIX` | The position was measured more than `geolocation_max_age_seconds` before Didit received it. | `geolocation_stale_fix_action` | `REVIEW` |
| `LOCATION_APPROXIMATE_ONLY` | A precise location was required and the person granted an approximate one (iOS reduced accuracy, Android "Approximate"). Never raised on web, which cannot tell. | `geolocation_approximate_action` | `REVIEW` |
| `LOCATION_CLOCK_SKEW` | The device said it measured the position in the future compared with Didit's clock. Informational only: freshness uses Didit's receipt time. | none | information |

### Spoofing and integrity

| Risk | Trigger | Config key | Default |
| - | - | - | - |
| `LOCATION_MOCK_PROVIDER_DETECTED` | Android reported the position came from a mock location provider. Testing and accessibility tools set it too, so the action is configurable. | `geolocation_mock_location_action` | `REVIEW` |
| `LOCATION_SIMULATED_BY_SOFTWARE` | iOS reported the position was simulated by software. | `geolocation_mock_location_action` | `REVIEW` |
| `LOCATION_INTEGRITY_MISSING` | A native app sent a position with no device attestation. Web is recorded as unsupported, not missing. | `geolocation_integrity_missing_action` | `NO_ACTION` |
| `LOCATION_EMULATOR_DETECTED` | The app reported running on an emulator or virtual machine. Browsers cannot report this. Unless the action is `NO_ACTION`, it ends the step on that attempt. | `geolocation_emulator_action` | `NO_ACTION` |
| `LOCATION_VPN_DETECTED` | The connection that shared the location exits through a commercial VPN. Unless the action is `NO_ACTION`, the person is asked to turn it off and check again. | `geolocation_vpn_action` | `NO_ACTION` |
| `LOCATION_PROXY_DETECTED` | The connection goes through an open, anonymous or private-relay proxy. | `geolocation_proxy_action` | `NO_ACTION` |
| `LOCATION_TOR_DETECTED` | The connection is a Tor exit node. | `geolocation_tor_action` | `NO_ACTION` |

### Areas

| Risk | Trigger | Config key | Default |
| - | - | - | - |
| `LOCATION_OUTSIDE_GEOFENCE` | The position and its whole accuracy circle are outside every allowed area. | `geolocation_geofencing_action` | `DECLINE` |
| `LOCATION_GEOFENCE_UNDETERMINED` | The accuracy circle reaches an edge that decides the answer, or the position resolves to no country. Uncertainty is never reported as outside. | `geolocation_geofence_undetermined_action` | `REVIEW` |
| `LOCATION_IN_BLOCKED_AREA` | The position and its whole accuracy circle are inside a blocked area. It is added to the allowed-area verdict, never in place of it, and the stricter action decides. | `geolocation_blocked_area_action` | `DECLINE` |

### Distance and history

| Risk | Trigger | Config key | Default |
| - | - | - | - |
| `LOCATION_IP_DISTANCE_MISMATCH` | The device position and the IP location are further apart than `geolocation_ip_distance_km`, after subtracting both radii. A VPN, a corporate proxy or a carrier's central exit produce this legitimately. | `geolocation_ip_distance_action` | `REVIEW` |
| `LOCATION_DOCUMENT_DISTANCE_MISMATCH` | The position is further than `geolocation_document_distance_km` from the document address. A weak signal, because addresses are geocoded coarsely and people travel. | `geolocation_document_distance_action` | `REVIEW` |
| `LOCATION_CONSECUTIVE_MISMATCHES` | This check and the same person's earlier checks (same `vendor_data`) were outside an allowed area, in a blocked area or too far from the address at least `geolocation_consecutive_mismatch_count` times in a row. | `geolocation_consecutive_mismatch_action` | `REVIEW` |

## What the person sees

Some findings are never explained to the person, because naming the signal tells a fraudster what to change.
`LOCATION_EMULATOR_DETECTED`, `LOCATION_MOCK_PROVIDER_DETECTED`, `LOCATION_SIMULATED_BY_SOFTWARE`, `LOCATION_REPLAY_DETECTED`, `LOCATION_INTEGRITY_FAILED` and `LOCATION_IP_DISTANCE_MISMATCH` are in that group: if a reviewer sends the verification back, the person reads a generic reason, while the decision payload and your webhooks keep the full warning.
A VPN is shown to the person only as a request to turn off any VPN and try again, and a blocked area is shown only as the list of places where the service is available.

## Example

```json theme={null}
{
  "risk": "LOCATION_LOW_ACCURACY",
  "log_type": "warning",
  "short_description": "Device location accuracy below the configured limit",
  "additional_data": {
    "accuracy_m": 1200.0,
    "accuracy_confidence": "p95",
    "max_accuracy_radius_m": 250
  },
  "node_id": "geolocation_1"
}
```

## Warning types

Each risk is assigned a severity based on your application's configuration. The three severities are:

## Related

* [Location verification report](https://docs.didit.me/core-technology/location-verification/report-location-verification.md) - the fields next to `warnings[]`.
* [Location verification](https://docs.didit.me/core-technology/location-verification/overview.md) - how the step works.
* [Workflow feature configs](https://docs.didit.me/management-api/workflows/feature-configs.md#location-verification) - every action key.
* [Data models - Warning object](https://docs.didit.me/reference/data-models.md#warning-object) - the shape of every entry in `warnings[]`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.