pixellint

vendor/singular · vendor documented

Singular EVENT is form fields, not JSON

v1 and v2 /evt take query or form parameters. p is a documented platform string, case-sensitive. n is 1 to 32 ASCII characters. Exactly one of ip or use_ip.

Platform spelling is case-sensitive

Singular documents iOS, Android, Web, and the rest with that capitalization. ios is not iOS. The call can still return 200.

Rule: vendor.singular.param.p.invalid

What this pack matches

Hosts
s2s.singular.net
Paths
…/api/v1/evt…, …/api/v2/evt…
Vendor docs
support.singular.net/hc/en-us/articles/31496864868635-Server-to-Server-EVENT-Endpoint-API-Reference

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
a required It is the Singular SDK Key, not the Reporting API Key, and every EVENT request requires it. Fix: Send the SDK Key as `a`. vendor.singular.param.a.missing
vendor.singular.param.a.empty
docs
p required It is the platform, case-sensitive. Singular documents the values Android, iOS, Web, PC, Xbox, Playstation, Nintendo, MetaQuest, and CTV. Fix: Set `p` to the documented platform spelling, such as `iOS`. vendor.singular.param.p.missing
vendor.singular.param.p.empty
vendor.singular.param.p.invalid
docs
i required It is the app identifier, case-sensitive, and every EVENT request requires it. Fix: Send the app ID as `i`. vendor.singular.param.i.missing
vendor.singular.param.i.empty
docs
n required It is the event name, at most 32 ASCII characters, and every EVENT request requires it. Fix: Set `n` to an event name of 32 ASCII characters or fewer. vendor.singular.param.n.missing
vendor.singular.param.n.empty
vendor.singular.param.n.invalid
docs
ip optional It is the public device IP. Singular requires `ip` or `use_ip`, and they are mutually exclusive. Fix: Send the device IPv4 as `ip`, or send `use_ip` instead. vendor.singular.param.ip.empty docs
use_ip optional It tells Singular to use the request IP. Mutually exclusive with `ip`. vendor.singular.param.use_ip.empty docs
sdid optional It is the Singular device ID, a UUIDv4. V2 requires it. New accounts as of 15 July 2026 must use V2. Fix: On `/api/v2/evt`, send `sdid` as a UUIDv4. vendor.singular.param.sdid.empty
vendor.singular.param.sdid.invalid
docs
cur optional It is an ISO 4217 currency code, uppercase, used with `amt` on revenue events. Fix: Send `cur` as `USD` together with `amt`. vendor.singular.param.cur.empty
vendor.singular.param.cur.invalid
docs
amt optional It is the revenue amount. Sending it makes the call a revenue event. vendor.singular.param.amt.empty docs
ip_required required The request has neither `ip` nor `use_ip`. Singular requires one of them on every EVENT. Fix: Send the device IP as `ip`, or send `use_ip` to use the request address. vendor.singular.ip_required docs
ip_ambiguous required The request sends both `ip` and `use_ip`. Singular documents them as mutually exclusive. Fix: Send only `ip` or only `use_ip`. vendor.singular.ip_ambiguous docs
hashed_plaintext_field required `ip` looks like a SHA-256 digest, but Singular documents it as the public device IP, unhashed. Fix: Send the raw IP address. vendor.singular.hashed_plaintext_field docs

Validate a payload

pixellint validate url "$ARTIFACT" --rulepack vendor/singular

Or paste it into the playground. Same engine, in the browser, nothing sent anywhere.

cargo install pixellint · npm install pixellint