HTTP endpoints
attachReferralCode
POST /api/v1/referrals/code
Requires partners:write. Keep the Bearer key on your server.
SDK
grizzlee.attachReferralCode(input: { referralCode: string; customerId: string; programId?: string | undefined; customerDisplayName?: string | undefined; orderId?: string | undefined; signals?: { email?: string | undefined; phone?: string | undefined; phoneHash?: string | undefined; paymentFingerprint?: string | undefined; deviceId?: string | undefined; ipAddress?: string | undefined; } | undefined; channel?: "link" | "qr" | "coupon" | "in_app" | undefined; }): Promise<AttachReferralCodeResponse>HTTP
Use your backend's HTTP client. The cURL request shows the wire format. Replace path parameters and example values.
curl --fail-with-body --request POST \
'https://app.grizzlee.ca/api/v1/referrals/code' \
-H "Authorization: Bearer $GRIZZLEE_SERVER_KEY" \
-H 'Content-Type: application/json' \
--data '{"customerId":"customer-example","orderId":"order-example","referralCode":"EXAMPLE"}'Request body
| Field | Type | Required | Details |
|---|---|---|---|
programId | string | No | |
customerId | string | Yes | |
customerDisplayName | string | No | |
orderId | string | No | |
referralCode | string | Yes | |
channel | "link", "qr", "coupon", "in_app" | No | default "coupon" |
signals | object | No |
signals
| Field | Type | Required | Details |
|---|---|---|---|
signals.email | string | No | |
signals.phone | string | No | |
signals.phoneHash | string | No | |
signals.paymentFingerprint | string | No | |
signals.deviceId | string | No | |
signals.ipAddress | string | No |
Request schema
{
"type": "object",
"properties": {
"programId": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"customerId": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"customerDisplayName": {
"type": "string",
"minLength": 1,
"maxLength": 80
},
"orderId": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"referralCode": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"channel": {
"type": "string",
"enum": [
"link",
"qr",
"coupon",
"in_app"
],
"default": "coupon"
},
"signals": {
"type": "object",
"properties": {
"email": {
"type": "string",
"maxLength": 254
},
"phone": {
"type": "string",
"maxLength": 40
},
"phoneHash": {
"type": "string",
"pattern": "^[0-9a-fA-F]{64}$"
},
"paymentFingerprint": {
"type": "string",
"minLength": 1,
"maxLength": 255
},
"deviceId": {
"type": "string",
"minLength": 1,
"maxLength": 255
},
"ipAddress": {
"type": "string",
"maxLength": 64
}
},
"additionalProperties": false
}
},
"required": [
"customerId",
"referralCode"
],
"additionalProperties": false
}Response
HTTP responses wrap this value in data. The SDK returns the value directly unless the note above describes a wrapper.
| Field | Type | Required | Details |
|---|---|---|---|
receipt | string | Yes | |
programId | string | Yes | |
placements | array | Yes | |
partnerId | string | Yes | |
partnerExternalId | string | Yes | |
expiresAt | string | Yes | |
duration | union | Yes | |
incentive | union | Yes | The program's current friend incentive, or null when it has none. Says nothing about eligibility. |
display | union | Yes | The program's public name, headline and milestone label. Null when the program is gone. |
attribution | object | No | Present for customer programs. It may retain a previously qualified partner. |
selfReferral | object | No | Present when customer links or identity signals match the partner: review or flagged. A blocked match throws self_referral. |
duration
Variant 1
Type: string.
Variant 2
Type: string.
Variant 3
Type: string.
Variant 4
Type: string.
Variant 5
Type: string.
Variant 6
Type: string.
incentive
Variant 1
Type: null.
Variant 2
| Field | Type | Required | Details |
|---|---|---|---|
incentive.type | "percent" | Yes | |
incentive.rateBps | number | Yes | |
incentive.orders | number | Yes | How many of the friend's orders get the incentive. |
incentive.newCustomersOnly | boolean | Yes | true: use the merchant's newCustomer answer, or recorded purchases when omitted. false: returning customers qualify too. A supplied answer uses the order limit after the referral. |
incentive.expiresAfterDays | union | Yes | Days after the referral was captured, claimed or entered. null means it never expires. |
incentive.returnOnFullRefund | boolean | Yes | true: a full refund gives the use back, so the customer can get the offer again. |
incentive.maxDiscountCents | number | No | Largest discount for one order. |
incentive.minOrderCents | number | No | The friend's order total before the discount must reach this amount. Checked by the merchant's checkout. |
incentive.orderCategories | object | No | Order categories that get the discount. Checked apart from the program's own orderCategories, which decide rewards. Absent means every order qualifies. |
incentive.currency | union | Yes |
incentive.expiresAfterDays
Variant 1
Type: null.
Variant 2
Type: number.
incentive.orderCategories
| Field | Type | Required | Details |
|---|---|---|---|
incentive.orderCategories.include | array | No | |
incentive.orderCategories.exclude | array | No |
incentive.currency
Variant 1
Type: string.
Variant 2
Type: string.
Variant 3
Type: string.
Variant 4
Type: string.
Variant 3
| Field | Type | Required | Details |
|---|---|---|---|
incentive.type | "fixed" | Yes | |
incentive.orders | number | Yes | How many of the friend's orders get the incentive. |
incentive.newCustomersOnly | boolean | Yes | true: use the merchant's newCustomer answer, or recorded purchases when omitted. false: returning customers qualify too. A supplied answer uses the order limit after the referral. |
incentive.expiresAfterDays | union | Yes | Days after the referral was captured, claimed or entered. null means it never expires. |
incentive.returnOnFullRefund | boolean | Yes | true: a full refund gives the use back, so the customer can get the offer again. |
incentive.amountCents | number | Yes | |
incentive.minOrderCents | number | No | The friend's order total before the discount must reach this amount. Checked by the merchant's checkout. |
incentive.orderCategories | object | No | Order categories that get the discount. Checked apart from the program's own orderCategories, which decide rewards. Absent means every order qualifies. |
incentive.currency | union | Yes |
incentive.expiresAfterDays
Variant 1
Type: null.
Variant 2
Type: number.
incentive.orderCategories
| Field | Type | Required | Details |
|---|---|---|---|
incentive.orderCategories.include | array | No | |
incentive.orderCategories.exclude | array | No |
incentive.currency
Variant 1
Type: string.
Variant 2
Type: string.
Variant 3
Type: string.
Variant 4
Type: string.
display
Variant 1
Type: null.
Variant 2
| Field | Type | Required | Details |
|---|---|---|---|
display.publicName | object | Yes | |
display.headline | object | Yes | |
display.milestoneLabel | union | Yes | Null for order programs. Forms by plural category, picked with Intl.PluralRules. few and many matter in Russian. A merchant's label sets one and other, and few and many reuse other. |
display.publicName
| Field | Type | Required | Details |
|---|---|---|---|
display.publicName.en | string | Yes | |
display.publicName.fr-CA | string | Yes | |
display.publicName.hy | string | Yes | |
display.publicName.ru | string | Yes |
display.headline
| Field | Type | Required | Details |
|---|---|---|---|
display.headline.en | string | Yes | |
display.headline.fr-CA | string | Yes | |
display.headline.hy | string | Yes | |
display.headline.ru | string | Yes |
display.milestoneLabel
Variant 1
Type: null.
Variant 2
| Field | Type | Required | Details |
|---|---|---|---|
display.milestoneLabel.one | object | Yes | |
display.milestoneLabel.few | object | Yes | |
display.milestoneLabel.many | object | Yes | |
display.milestoneLabel.other | object | Yes |
display.milestoneLabel.one
| Field | Type | Required | Details |
|---|---|---|---|
display.milestoneLabel.one.en | string | Yes | |
display.milestoneLabel.one.fr-CA | string | Yes | |
display.milestoneLabel.one.hy | string | Yes | |
display.milestoneLabel.one.ru | string | Yes |
display.milestoneLabel.few
| Field | Type | Required | Details |
|---|---|---|---|
display.milestoneLabel.few.en | string | Yes | |
display.milestoneLabel.few.fr-CA | string | Yes | |
display.milestoneLabel.few.hy | string | Yes | |
display.milestoneLabel.few.ru | string | Yes |
display.milestoneLabel.many
| Field | Type | Required | Details |
|---|---|---|---|
display.milestoneLabel.many.en | string | Yes | |
display.milestoneLabel.many.fr-CA | string | Yes | |
display.milestoneLabel.many.hy | string | Yes | |
display.milestoneLabel.many.ru | string | Yes |
display.milestoneLabel.other
| Field | Type | Required | Details |
|---|---|---|---|
display.milestoneLabel.other.en | string | Yes | |
display.milestoneLabel.other.fr-CA | string | Yes | |
display.milestoneLabel.other.hy | string | Yes | |
display.milestoneLabel.other.ru | string | Yes |
attribution
| Field | Type | Required | Details |
|---|---|---|---|
attribution.id | string | Yes | |
attribution.companyId | string | Yes | |
attribution.partnerId | string | Yes | |
attribution.qualifiedAt | string | No | |
attribution.qualifiedOrderNumber | number | No | |
attribution.programId | string | Yes | |
attribution.referralCode | string | Yes | |
attribution.customerId | string | Yes | |
attribution.occurredAt | string | Yes | |
attribution.channel | union | Yes | |
attribution.providerPromoCodeId | string | No | |
attribution.customerDisplayName | string | No | |
attribution.orderId | string | No |
attribution.channel
Variant 1
Type: string.
Variant 2
Type: string.
Variant 3
Type: string.
Variant 4
Type: string.
selfReferral
| Field | Type | Required | Details |
|---|---|---|---|
selfReferral.action | union | Yes | |
selfReferral.signals | array | Yes |
selfReferral.action
Variant 1
Type: string.
Variant 2
Type: string.
Variant 3
Type: string.
selfReferral.signals[]
Variant 1
Type: string.
Variant 2
Type: string.
Variant 3
Type: string.
Variant 4
Type: string.
Variant 5
Type: string.
Variant 6
Type: string.
Response schema
{
"type": "object",
"properties": {
"receipt": {
"type": "string"
},
"programId": {
"type": "string"
},
"placements": {
"type": "array",
"items": {
"type": "string"
}
},
"partnerId": {
"type": "string"
},
"partnerExternalId": {
"type": "string"
},
"expiresAt": {
"type": "string"
},
"duration": {
"anyOf": [
{
"type": "string",
"const": "only_order"
},
{
"type": "string",
"const": "first_order"
},
{
"type": "string",
"const": "first_n_orders"
},
{
"type": "string",
"const": "days"
},
{
"type": "string",
"const": "months"
},
{
"type": "string",
"const": "lifetime"
}
]
},
"incentive": {
"anyOf": [
{
"type": "null"
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "percent"
},
"rateBps": {
"type": "number"
},
"orders": {
"type": "number",
"description": "How many of the friend's orders get the incentive."
},
"newCustomersOnly": {
"type": "boolean",
"description": "true: use the merchant's newCustomer answer, or recorded purchases when omitted. false:\nreturning customers qualify too. A supplied answer uses the order limit after the referral."
},
"expiresAfterDays": {
"anyOf": [
{
"type": "null"
},
{
"type": "number"
}
],
"description": "Days after the referral was captured, claimed or entered. null means it never expires."
},
"returnOnFullRefund": {
"type": "boolean",
"description": "true: a full refund gives the use back, so the customer can get the offer again."
},
"maxDiscountCents": {
"type": "number",
"description": "Largest discount for one order."
},
"minOrderCents": {
"type": "number",
"description": "The friend's order total before the discount must reach this amount. Checked by the merchant's checkout."
},
"orderCategories": {
"type": "object",
"properties": {
"include": {
"type": "array",
"items": {
"type": "string"
}
},
"exclude": {
"type": "array",
"items": {
"type": "string"
}
}
},
"description": "Order categories that get the discount. Checked apart from the program's own orderCategories,\nwhich decide rewards. Absent means every order qualifies."
},
"currency": {
"anyOf": [
{
"type": "string",
"const": "CAD"
},
{
"type": "string",
"const": "USD"
},
{
"type": "string",
"const": "EUR"
},
{
"type": "string",
"const": "GBP"
}
]
}
},
"required": [
"type",
"rateBps",
"orders",
"newCustomersOnly",
"expiresAfterDays",
"returnOnFullRefund",
"currency"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "fixed"
},
"orders": {
"type": "number",
"description": "How many of the friend's orders get the incentive."
},
"newCustomersOnly": {
"type": "boolean",
"description": "true: use the merchant's newCustomer answer, or recorded purchases when omitted. false:\nreturning customers qualify too. A supplied answer uses the order limit after the referral."
},
"expiresAfterDays": {
"anyOf": [
{
"type": "null"
},
{
"type": "number"
}
],
"description": "Days after the referral was captured, claimed or entered. null means it never expires."
},
"returnOnFullRefund": {
"type": "boolean",
"description": "true: a full refund gives the use back, so the customer can get the offer again."
},
"amountCents": {
"type": "number"
},
"minOrderCents": {
"type": "number",
"description": "The friend's order total before the discount must reach this amount. Checked by the merchant's checkout."
},
"orderCategories": {
"type": "object",
"properties": {
"include": {
"type": "array",
"items": {
"type": "string"
}
},
"exclude": {
"type": "array",
"items": {
"type": "string"
}
}
},
"description": "Order categories that get the discount. Checked apart from the program's own orderCategories,\nwhich decide rewards. Absent means every order qualifies."
},
"currency": {
"anyOf": [
{
"type": "string",
"const": "CAD"
},
{
"type": "string",
"const": "USD"
},
{
"type": "string",
"const": "EUR"
},
{
"type": "string",
"const": "GBP"
}
]
}
},
"required": [
"type",
"orders",
"newCustomersOnly",
"expiresAfterDays",
"returnOnFullRefund",
"amountCents",
"currency"
]
}
],
"description": "The program's current friend incentive, or null when it has none. Says nothing about eligibility."
},
"display": {
"anyOf": [
{
"type": "null"
},
{
"type": "object",
"properties": {
"publicName": {
"type": "object",
"properties": {
"en": {
"type": "string"
},
"fr-CA": {
"type": "string"
},
"hy": {
"type": "string"
},
"ru": {
"type": "string"
}
},
"required": [
"en",
"fr-CA",
"hy",
"ru"
]
},
"headline": {
"type": "object",
"properties": {
"en": {
"type": "string"
},
"fr-CA": {
"type": "string"
},
"hy": {
"type": "string"
},
"ru": {
"type": "string"
}
},
"required": [
"en",
"fr-CA",
"hy",
"ru"
]
},
"milestoneLabel": {
"anyOf": [
{
"type": "null"
},
{
"type": "object",
"properties": {
"one": {
"type": "object",
"properties": {
"en": {
"type": "string"
},
"fr-CA": {
"type": "string"
},
"hy": {
"type": "string"
},
"ru": {
"type": "string"
}
},
"required": [
"en",
"fr-CA",
"hy",
"ru"
]
},
"few": {
"type": "object",
"properties": {
"en": {
"type": "string"
},
"fr-CA": {
"type": "string"
},
"hy": {
"type": "string"
},
"ru": {
"type": "string"
}
},
"required": [
"en",
"fr-CA",
"hy",
"ru"
]
},
"many": {
"type": "object",
"properties": {
"en": {
"type": "string"
},
"fr-CA": {
"type": "string"
},
"hy": {
"type": "string"
},
"ru": {
"type": "string"
}
},
"required": [
"en",
"fr-CA",
"hy",
"ru"
]
},
"other": {
"type": "object",
"properties": {
"en": {
"type": "string"
},
"fr-CA": {
"type": "string"
},
"hy": {
"type": "string"
},
"ru": {
"type": "string"
}
},
"required": [
"en",
"fr-CA",
"hy",
"ru"
]
}
},
"required": [
"one",
"few",
"many",
"other"
]
}
],
"description": "Null for order programs. Forms by plural category, picked with Intl.PluralRules. few and\nmany matter in Russian. A merchant's label sets one and other, and few and many reuse other."
}
},
"required": [
"publicName",
"headline",
"milestoneLabel"
]
}
],
"description": "The program's public name, headline and milestone label. Null when the program is gone."
},
"attribution": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"companyId": {
"type": "string"
},
"partnerId": {
"type": "string"
},
"qualifiedAt": {
"type": "string"
},
"qualifiedOrderNumber": {
"type": "number"
},
"programId": {
"type": "string"
},
"referralCode": {
"type": "string"
},
"customerId": {
"type": "string"
},
"occurredAt": {
"type": "string"
},
"channel": {
"anyOf": [
{
"type": "string",
"const": "link"
},
{
"type": "string",
"const": "qr"
},
{
"type": "string",
"const": "coupon"
},
{
"type": "string",
"const": "in_app"
}
]
},
"providerPromoCodeId": {
"type": "string"
},
"customerDisplayName": {
"type": "string"
},
"orderId": {
"type": "string"
}
},
"required": [
"id",
"companyId",
"partnerId",
"programId",
"referralCode",
"customerId",
"occurredAt",
"channel"
],
"description": "Present for customer programs. It may retain a previously qualified partner."
},
"selfReferral": {
"type": "object",
"properties": {
"action": {
"anyOf": [
{
"type": "string",
"const": "blocked"
},
{
"type": "string",
"const": "review"
},
{
"type": "string",
"const": "flagged"
}
]
},
"signals": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string",
"const": "email"
},
{
"type": "string",
"const": "phone"
},
{
"type": "string",
"const": "card"
},
{
"type": "string",
"const": "device"
},
{
"type": "string",
"const": "ip"
},
{
"type": "string",
"const": "customer_id"
}
]
}
}
},
"required": [
"action",
"signals"
],
"description": "Present when customer links or identity signals match the partner: review or flagged. A blocked match throws self_referral."
}
},
"required": [
"receipt",
"programId",
"placements",
"partnerId",
"partnerExternalId",
"expiresAt",
"duration",
"incentive",
"display"
]
}Errors
Failures return { "error": { "code": "...", "message": "...", "details": {} } }. Details are optional. See error statuses. Reuse an unchanged event payload when retrying.