Signs and validates the deeplink tokens that authorize third-party-channel deeplinks (links.pidgr.com/c/{short_code}?t={token}). Each token carries the (campaign, recipient, step) tuple, is signed with a per-organization key, and expires. Key rotation is automatic with a 7-day overlap window, so callers never have to coordinate around it.
| Method |
Description |
SignDeeplinkToken |
Sign a deeplink token (internal only) |
ValidateDeeplinkToken |
Validate a deeplink token and decode its payload |
Returned in ValidateDeeplinkTokenResponse.failure_reason when valid is false.
| Value |
Description |
VALIDATION_FAILURE_REASON_INVALID_SIGNATURE |
Token bytes parsed but the signature did not verify under any active or overlap-window key version. |
VALIDATION_FAILURE_REASON_EXPIRED |
Token signature verified but its embedded expiry has passed. |
VALIDATION_FAILURE_REASON_KEY_RETIRED |
The key version that signed the token is past the rotation overlap window. Operationally equivalent to EXPIRED but distinguishable for telemetry. |
VALIDATION_FAILURE_REASON_MALFORMED |
Token bytes could not be parsed at all. Indicates a tampered or truncated URL. |
Sign a deeplink token for a (campaign, recipient, step) tuple.
Authorization: Internal service only (called by the dispatch layer assembling a deeplink during message composition)
| Field |
Type |
Description |
campaign_id |
string |
Campaign whose deeplink this token authorizes. Required; must be a UUID and exist within the caller’s organization. |
recipient_user_id |
string |
Recipient the token authorizes. Required; must be a UUID and a member of the campaign’s audience. |
step_kind |
ChannelStepKind |
Step kind the deeplink targets. Required. |
ttl_seconds |
int64 |
Token lifetime in seconds from now. Required; must be between 1 second and 30 days. Longer tokens are not signed. |
| Field |
Type |
Description |
token |
string |
The signed token, ready to URL-embed in links.pidgr.com/c/{short_code}?t={token}. Opaque — clients should not parse or mutate it; pass it back to ValidateDeeplinkToken. |
expires_at |
Timestamp |
The expiry the token carries. |
key_version |
int32 |
Key version used to sign. May be recorded for telemetry, but clients should not branch logic on it — rotation overlap windows are managed transparently. |
Validate a deeplink token before showing the sign-in gate. The token itself is the lookup key; valid responses carry the decoded payload. The token does not authenticate the recipient (that is the sign-in flow’s job) — it authorizes “this deeplink path is for this recipient”, so the app can refuse to render a token whose embedded recipient mismatches the signed-in user.
Authorization: Public (no authentication required) — called by the app before the sign-in gate
| Field |
Type |
Description |
token |
string |
The token bytes from the deeplink URL’s t query parameter. Required, non-empty. |
campaign_id |
string |
Campaign UUID from the URL path (translated from the short code via CampaignService.GetCampaignByShortCode). Validation rejects tokens whose embedded campaign_id does not match — defense against replaying a token from a different campaign. |
| Field |
Type |
Description |
valid |
bool |
True when signature and expiry both check out under any active or overlap-window key version. |
failure_reason |
ValidationFailureReason |
Reason validation failed. Set only when valid is false; UNSPECIFIED when valid. Drives client UX (silent retry vs “this link expired” vs “this link looks tampered”). |
payload |
DeeplinkTokenPayload |
Decoded payload. Populated only when valid is true. |
| Field |
Type |
Description |
campaign_id |
string |
Campaign UUID the deeplink targets. Used for the authenticated GetCampaign follow-up after the recipient signs in. |
recipient_user_id |
string |
Recipient UUID the token authorizes. Clients should compare this against the signed-in user and refuse to render the campaign card on mismatch. |
step_kind |
ChannelStepKind |
Step kind the deeplink targets — reminder vs escalation. Lets the client pick the right campaign-card variant before the sign-in gate. |
expires_at |
Timestamp |
Expiry the token carries. Validation rejects tokens past this time even if the signature checks out. |