AppsFlyer web visits validate their captured endpoint contracts.
The web visit operation belongs to events.appsflyer.com/v2.0/s2s/visits/app/web/{appId}. Its payload rules require captured HTTP endpoint context. Bare JSON cannot establish this operation, and the mobile S2S body remains a separate contract.
A top-level user_id object must contain customer_user_id, appsflyer_id or both. event_url is required and must be an HTTP or HTTPS URL of at most 4,096 characters. Unknown fields and custom parameters remain open.
Observed requests require POST, application/json and a populated Authorization Bearer token. Unavailable or redacted evidence is deferred. Live token/app ownership, late-arrival configuration, prior visits and hash preimages remain external.
The explicit endpoint tables require top-level user_id. A separate integration paragraph describes a conflicting nested wrapper. These checks follow the endpoint tables, document that conflict, and do not silently accept a nested alias or claim complete receiver acceptance.
At least one supported identity is required.
An empty user_id object has no supported identity. Either customer_user_id or appsflyer_id is sufficient; supplied values retain native string and length checks. The pack does not infer a UUID grammar or a prior identified session.
Rule: vendor.appsflyer-web-visit.http.user_id.identifier_required
A hash must contain exactly 64 hexadecimal characters.
The five optional hashed identity fields accept both uppercase and lowercase hex letters. A digest does not establish correct preimage normalization. Empty or nonhex supplied hashes fail their own local representation checks.
A visit needs a valid page URL.
event_url is required on the visit route. It must use HTTP or HTTPS and stay within the documented character limit. The optional event URL on the event route has a separate presence contract.
A nested user wrapper does not supply the required root identity.
The published endpoint table uses a top-level user_id object. A nested user.user_id value does not satisfy that field. The source inconsistency remains in the audit; unknown fields and custom parameters stay open.
What this pack matches
Rules
Codes are stable. A finding in CI, MCP, or the playground lands on the same id.
| Field | Required | What it checks | Rule ids | Source |
|---|---|---|---|---|
app_id |
required | Required dashboard unified_app_id. Website prefixes and registration truth are not inferred from examples. | vendor.appsflyer-web-visit.param.app_id.missingvendor.appsflyer-web-visit.param.app_id.empty |
docs |
method |
required | The published operation uses POST. Complete HTTP capture contract. Native JSON type: string. | vendor.appsflyer-web-visit.http.method.missingvendor.appsflyer-web-visit.http.method.emptyvendor.appsflyer-web-visit.http.method.invalid |
docs |
content_type |
required | All requests require application/json. Complete HTTP capture contract. Native JSON type: string. | vendor.appsflyer-web-visit.http.content_type.missingvendor.appsflyer-web-visit.http.content_type.emptyvendor.appsflyer-web-visit.http.content_type.invalid |
docs |
body_encoding |
required | This operation carries a JSON entity. A locally unsupported decoder representation remains unvalidated. Complete HTTP capture contract. Applies when {"kind":"not","condition":{"kind":"value_in","param":"body_encoding","values":["unsupported"]}}. Native JSON type: string. | vendor.appsflyer-web-visit.http.body_encoding.missingvendor.appsflyer-web-visit.http.body_encoding.emptyvendor.appsflyer-web-visit.http.body_encoding.invalid |
docs |
headers.authorization |
required | The published API requires an Authorization Bearer S2S token. Token validity and ownership remain external. Complete HTTP capture contract. Native JSON type: string. | vendor.appsflyer-web-visit.http.headers.authorization.missingvendor.appsflyer-web-visit.http.headers.authorization.emptyvendor.appsflyer-web-visit.http.headers.authorization.invalid |
docs |
url |
required | The published endpoint uses HTTPS. Complete HTTP capture contract. Native JSON type: string. | vendor.appsflyer-web-visit.http.url.missingvendor.appsflyer-web-visit.http.url.emptyvendor.appsflyer-web-visit.http.url.invalid |
docs |
body |
required | The endpoint body is a JSON object. Complete HTTP capture contract. Native JSON type: object. | vendor.appsflyer-web-visit.http.body.missingvendor.appsflyer-web-visit.http.body.invalid |
docs |
user_id |
required | The published web table requires a top-level user_id object with at least one documented identifier. Complete HTTP capture contract. Capture scope: body. Native JSON type: object. | vendor.appsflyer-web-visit.http.user_id.missingvendor.appsflyer-web-visit.http.user_id.invalid |
docs |
event_url |
required | The documented page URL uses HTTP or HTTPS and is at most 4096 characters. Complete HTTP capture contract. Capture scope: body. Presence diagnostic severity: error. Native JSON type: string. Maximum decoded characters: 4096. | vendor.appsflyer-web-visit.http.event_url.missingvendor.appsflyer-web-visit.http.event_url.emptyvendor.appsflyer-web-visit.http.event_url.invalid |
docs |
event_value |
optional | Optional free-form event parameters remain an open object. Complete HTTP capture contract. Capture scope: body. Native JSON type: object. | vendor.appsflyer-web-visit.http.event_value.invalid |
docs |
event_value.custom_parameters |
optional | The documented custom_parameters representation is a sub-object. Complete HTTP capture contract. Capture scope: body. Native JSON type: object. | vendor.appsflyer-web-visit.http.event_value.custom_parameters.invalid |
docs |
timestamp |
optional | Optional Unix milliseconds use the published int64 type. App timezone and receipt time are external. Complete HTTP capture contract. Capture scope: body. Native JSON type: integer. Minimum numeric value: -9223372036854776000. Maximum numeric value: 9223372036854776000. | vendor.appsflyer-web-visit.http.timestamp.invalid |
docs |
ip |
optional | Optional device IP accepts IPv4 or IPv6, up to 46 characters. Complete HTTP capture contract. Capture scope: body. Presence diagnostic severity: error. Native JSON type: string. Maximum decoded characters: 46. | vendor.appsflyer-web-visit.http.ip.emptyvendor.appsflyer-web-visit.http.ip.invalid |
docs |
user_agent |
optional | Optional browser user agent is at most 1024 characters. Complete HTTP capture contract. Capture scope: body. Native JSON type: string. Maximum decoded characters: 1024. | vendor.appsflyer-web-visit.http.user_agent.invalid |
docs |
http_referrer |
optional | The optional referrer is documented as a string. No extra length or scheme restriction is invented. Complete HTTP capture contract. Capture scope: body. Native JSON type: string. | vendor.appsflyer-web-visit.http.http_referrer.invalid |
docs |
email_hashed |
optional | The optional SHA256 representation must be exactly 64 hexadecimal characters. The preimage cannot be verified locally. Complete HTTP capture contract. Capture scope: body. Native JSON type: string. Minimum decoded characters: 64. Maximum decoded characters: 64. | vendor.appsflyer-web-visit.http.email_hashed.emptyvendor.appsflyer-web-visit.http.email_hashed.invalid |
docs |
phone_number_hashed |
optional | The optional SHA256 representation must be exactly 64 hexadecimal characters. The preimage cannot be verified locally. Complete HTTP capture contract. Capture scope: body. Native JSON type: string. Minimum decoded characters: 64. Maximum decoded characters: 64. | vendor.appsflyer-web-visit.http.phone_number_hashed.emptyvendor.appsflyer-web-visit.http.phone_number_hashed.invalid |
docs |
phone_number_e164_hashed |
optional | The optional SHA256 representation must be exactly 64 hexadecimal characters. The preimage cannot be verified locally. Complete HTTP capture contract. Capture scope: body. Native JSON type: string. Minimum decoded characters: 64. Maximum decoded characters: 64. | vendor.appsflyer-web-visit.http.phone_number_e164_hashed.emptyvendor.appsflyer-web-visit.http.phone_number_e164_hashed.invalid |
docs |
first_name_hashed |
optional | The optional SHA256 representation must be exactly 64 hexadecimal characters. The preimage cannot be verified locally. Complete HTTP capture contract. Capture scope: body. Native JSON type: string. Minimum decoded characters: 64. Maximum decoded characters: 64. | vendor.appsflyer-web-visit.http.first_name_hashed.emptyvendor.appsflyer-web-visit.http.first_name_hashed.invalid |
docs |
last_name_hashed |
optional | The optional SHA256 representation must be exactly 64 hexadecimal characters. The preimage cannot be verified locally. Complete HTTP capture contract. Capture scope: body. Native JSON type: string. Minimum decoded characters: 64. Maximum decoded characters: 64. | vendor.appsflyer-web-visit.http.last_name_hashed.emptyvendor.appsflyer-web-visit.http.last_name_hashed.invalid |
docs |
customer_dedup_id |
optional | The visit deduplication ID is an optional string with no published size or format limit. Complete HTTP capture contract. Capture scope: body. Native JSON type: string. | vendor.appsflyer-web-visit.http.customer_dedup_id.invalid |
docs |
http.event_url_http |
required | The documented page URL uses HTTP or HTTPS. Complete HTTP capture contract. Capture scope: body. | vendor.appsflyer-web-visit.http.event_url_http |
docs |
customer_user_id |
optional | Customer identifier is 1 to 64 characters. Complete HTTP capture contract. Capture scope: body.user_id. Native JSON type: string. Minimum decoded characters: 1. Maximum decoded characters: 64. | vendor.appsflyer-web-visit.http.customer_user_id.invalid |
docs |
appsflyer_id |
optional | AppsFlyer web identifier has at least one character. No upper limit is published. Complete HTTP capture contract. Capture scope: body.user_id. Native JSON type: string. Minimum decoded characters: 1. | vendor.appsflyer-web-visit.http.appsflyer_id.invalid |
docs |
http.user_id.identifier_required |
required | Provide at least one identifier in the top-level user_id object. Complete HTTP capture contract. Capture scope: body.user_id. | vendor.appsflyer-web-visit.http.user_id.identifier_required |
docs |
Validate a payload
pixellint validate request @request.json --rulepack vendor/appsflyer-web-visit
Try this failing payload in the playground. The web visit omits event_url.
{"url":"https://events.appsflyer.com/v2.0/s2s/visits/app/web/website-example.com","method":"POST","headers":{"Content-Type":"application/json","Authorization":"Bearer LOCAL_EXAMPLE_TOKEN"},"body":"{\"user_id\":{\"customer_user_id\":\"local-example-user\"}}"}
cargo install pixellint
·
npm install pixellint