Skip to main content

Collaborative Authorization

Overview

Collaborative authorization lets you approve or decline transactions in real time based on your business logic. Where Spend Rules and Velocity Controls are declarative rules that you configure, Collaborative Authorization is a real-time webhook-style feature where you respond with an approve or decline decision for each transaction. It runs after Highnote's built-in checks pass, giving you a final say before the authorization goes through.

initial authorizations only

Collaborative authorization requests are for initial authorizations only, not refund authorizations.

This guide covers how to configure and activate a collaborative authorization endpoint, verify requests, make real-time authorization decisions, and simulate authorizations in the Test environment.

Collaborative authorization flow

The following steps demonstrate how collaborative authorization typically works on a card product:

  1. An account holder makes a purchase which is sent to Highnote.
  2. The purchase is passed through financial account balance checks and spend rules configured on the Highnote platform.
  3. If the purchase passes these, an HTTPS POST request is sent to your collaborative authorization endpoint for approval.
  4. You respond to the request with an approval or denial decision.
  5. The authorization response is sent to the merchant with the decision.

These steps are depicted in the following graphic:

Collaborative Authorization Sequence

Enable the feature

info

Collaborative authorization is self-service in your Test environment. In the Live environment, this feature must be enabled for your product by the Highnote team.

To start using collaborative authorization, you must complete the following steps:

  1. Have the Highnote team enable the feature for your card product. Contact support@highnote.com.
  2. Register a collaborative authorization endpoint.
  3. Activate the collaborative authorization endpoint.
  4. Configure your request and response process.
  5. Optional - Test the feature.

Manage endpoints

You can manage collaborative authorization endpoints using the Highnote Dashboard or API.

via the Dashboard

When managing collaborative authorization endpoints using the Highnote Dashboard, refer to Collaborative authorization in the Support docs.

via the Highnote API

When managing collaborative authorization endpoints using the Highnote API, note the following:

  • You can have up to 5 collaborative authorization endpoints, but only 1 endpoint can be active at a time.
  • Collaborative authorization requests are sent as HTTPS POST requests with JSON bodies. The following headers are included on each request:
    • user-agent: HighnotePlatform/1.0.0
    • highnote-signature: The result of computing an HMAC 256 signature of the request body
    • content-type: application/json
prevent timing attacks

Always use constant-time comparison (like timingSafeEqual) to prevent timing attacks.

Register an endpoint

Use the following mutation to register and add a collaborative authorization endpoint. By default, collaborative authorization endpoints are inactive at creation.

When registering a collaborative authorization endpoint, refer to the following requirements:

  • Make the endpoint highly available.
  • The endpoint must be capable of returning a 2XX response. All other status codes result in the transaction being declined.
  • The endpoint requests and responses must be served via HTTPS.
AddCollaborativeAuthorizationEndpoint
Query
mutation AddCollaborativeAuthorizationEndpoint(
$input: AddCollaborativeAuthorizationEndpointInput!
) {
addCollaborativeAuthorizationEndpoint(input: $input) {
... on CollaborativeAuthorizationEndpoint {
id
name
uri
status
signingKeys {
id
secret
}
createdAt
updatedAt
}
... on UserError {
errors {
errorPath
code
description
}
}
}
}
Variables
{
  "input": {
    "name": "My Collaborative Auth Endpoint",
    "uri": "https://webhook.site"
  }
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"addCollaborativeAuthorizationEndpoint": {
"__typename": "CollaborativeAuthorizationEndpoint",
"id": "ENDPOINT_ID",
"name": "My Collaborative Auth Endpoint",
"uri": "https://webhook.site",
"createdAt": "2021-11-19T19:16:23.477Z",
"updatedAt": "2021-11-19T19:16:23.477Z",
"status": "PENDING_VERIFICATION",
"signingKeys": [
{
"id": "SIGNING_KEY_ID",
"secret": "some_secret"
}
]
}
},
"extensions": {
"requestId": "REQUEST_ID"
}
}

Activate an endpoint

one active endpoint

Only 1 endpoint can be ACTIVE at a time. Activating an endpoint automatically deactivates any existing active endpoints.

Once a collaborative authorization endpoint has been registered, you must activate and verify it. Use the following mutation to activate a collaborative authorization endpoint:

ActivateCollaborativeAuthorizationEndpoint
Query
mutation ActivateCollaborativeAuthorizationEndpoint(
$input: ActivateCollaborativeAuthorizationEndpointInput!
) {
activateCollaborativeAuthorizationEndpoint(input: $input) {
... on CollaborativeAuthorizationEndpoint {
id
name
uri
status
}
... on UserError {
errors {
errorPath
code
description
}
}
}
}
Variables
{
  "input": {
    "endpointId": "ENDPOINT_ID"
  }
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"activateCollaborativeAuthorizationEndpoint": {
"__typename": "CollaborativeAuthorizationEndpoint",
"id": "ENDPOINT_ID",
"name": "My Collaborative Auth Endpoint",
"uri": "https://webhook.site",
"status": "ACTIVE"
}
},
"extensions": {
"requestId": "REQUEST_ID"
}
}

Request and response guidelines

info

The collaborativeAuthorizationRequest.id is an idempotent key. In the event of a retry, Highnote resends the same request to your collaborative authorization endpoint with the same id.

Collaborative authorization request events differ from payment card authorization notification events.

Refer to the following guidelines for handling collaborative authorization requests and responses:

  • You have up to 2 seconds to respond to a collaborative authorization request with an approval or denial decision.
  • Returning any HTTP response code except 2XX causes the collaborative authorization request to fail and trigger your stand-in authorization settings.
  • Failure to respond to a request within 2 seconds causes the collaborative authorization request to fail and trigger your stand-in authorization settings.

When your endpoint fails to respond (timeout or non-2XX), Highnote uses your card product's stand-in settings to approve or decline the transaction. Contact support@highnote.com to configure stand-in behavior.

Request body

A collaborative authorization request is an HTTPS POST request with a JSON body.

Amount fields

A collaborative authorization request body has several amount fields relating to a transaction's money movement. These amount fields may differ from one request to another.

FieldDescription
transactionAmountThe amount the merchant requested for the transaction, displayed in the local (transaction) currency.
settlementAmountThe transactionAmount converted to the settlement currency.
requestedAmountThe amount of funds approved by the issuer in the settlement currency. May include surcharge fees. In some use cases, this value can exceed transactionAmount.

Other notes

  • The field "responseCode": "APPROVED" refers to Highnote's preliminary authorization decision before calling your endpoint.
  • The extensions object contains metadata about the request, specifically the signatureTimestamp which is the Unix timestamp (milliseconds) when the request was signed. Use this to verify request freshness and prevent replay attacks.

Example - US request payload

The following code snippet provides an example of a collaborative authorization request body.

{
"data": {
"collaborativeAuthorizationRequest": {
"__typename": "PaymentCardAuthorizationRequest",
"id": "te_01",
"transaction": {
"id": "tx_01"
},
"transactionTimestamp": "2022-12-07T20:57:26.052000000Z",
"paymentCard": { "id": "cd_01" },
"networkRetrievalReferenceNumber": null,
"transactionAmount": {
"value": 1000,
"currencyCode": "USD"
},
"settlementAmount": {
"value": 1000,
"currencyCode": "USD"
},
"requestedAmount": {
"value": 1000,
"currencyCode": "USD"
},
"surchargeFee": null,
"merchantDetails": {
"merchantId": "301100000m2d1gz",
"category": "MISCELLANEOUS_SPECIALTY_RETAIL",
"countryCodeAlpha3": "USA",
"categoryCode": "7399",
"description": "HNT*Highnote Biz Servi San Francisco USA",
"name": "HNT*Highnote Biz Servi",
"address": {
"streetAddress": "",
"extendedAddress": null,
"postalCode": "94107",
"region": "CA",
"locality": "SAN FRANCISCO",
"countryCodeAlpha3": "USA"
}
},
"responseCode": "APPROVED",
"avsResponseCode": "MATCH",
"postalCodeResponseCode": "MATCH",
"cvvResponseCode": "MATCH",
"pointOfSaleDetails": {
"panEntryMode": "CONTACTLESS_VIA_CHIP_RULES",
"pinEntryMode": null,
"terminalAttendance": "UNATTENDED",
"isCardHolderPresent": false,
"isCardPresent": false,
"purchaseAmountOnlyCapable": false,
"isRecurring": null,
"terminalSupportsPartialApproval": false
},
"createdAt": "2022-12-07T20:57:26.052000000Z"
}
},
"extensions": {
"signatureTimestamp": 1670446646658
}
}

Example - Cross-border request payload

The following code snippet provides an example of a cross-border collaborative authorization request body:

{
"data": {
"collaborativeAuthorizationRequest": {
"__typename": "PaymentCardAuthorizationRequest",
"id": "te_02",
"transaction": {
"id": "tx_02"
},
"transactionTimestamp": "2022-12-07T20:57:26.052000000Z",
"paymentCard": { "id": "cd_02" },
"networkRetrievalReferenceNumber": null,
"transactionAmount": {
"value": 1200,
"currencyCode": "CAD"
},
"settlementAmount": {
"value": 1000,
"currencyCode": "USD"
},
"requestedAmount": {
"value": 1000,
"currencyCode": "USD"
},
"surchargeFee": null,
"merchantDetails": {
"merchantId": "040080092661007",
"category": "MISCELLANEOUS_SPECIALTY_RETAIL",
"countryCodeAlpha3": "CAN",
"categoryCode": "5651",
"description": "HOMESENSE 013 ETOBICOKE CA",
"name": "HOMESENSE 013",
"address": {
"streetAddress": "",
"extendedAddress": null,
"postalCode": "M9C5H5000",
"region": 67,
"locality": "ETOBICOKE",
"countryCodeAlpha3": "CAN"
}
},
"responseCode": "APPROVED",
"avsResponseCode": "MATCH",
"postalCodeResponseCode": "MATCH",
"cvvResponseCode": "MATCH",
"pointOfSaleDetails": {
"panEntryMode": "CONTACTLESS_VIA_CHIP_RULES",
"pinEntryMode": null,
"terminalAttendance": "UNATTENDED",
"isCardHolderPresent": false,
"isCardPresent": false,
"purchaseAmountOnlyCapable": false,
"isRecurring": null,
"terminalSupportsPartialApproval": false
},
"createdAt": "2022-12-07T20:57:26.052000000Z"
}
},
"extensions": {
"signatureTimestamp": 1670446646658
}
}

Response

Collaborative authorization response bodies may have the following fields:

FieldDescription
transaction.idUnique identifier of the transaction
responseCodeTransaction authorization response
authorizedAmountAn Amount object

For a full list of collaborative authorization response codes, see CollaborativeAuthorizationResponseCode in the API reference.

Approved response

When your endpoint responds with the following payload, an AuthorizationEvent will reflect a status of APPROVED.

The following code snippet provides an example APPROVED response body:

Approved response
{
"transaction": {
"id": "tx_03"
},
"responseCode": "APPROVED"
}

Partial amount approved response

caution

For partial approvals, the authorizedAmount cannot be greater than the requestedAmount and must be expressed in the same currency.

When your endpoint responds with the following payload, an AuthorizationEvent reflects a status of PARTIAL_AMOUNT_APPROVED. The merchant must report whether their point of sale can accept a partial amount via the terminalSupportsPartialApproval field in the pointOfSaleDetails object:

Partial amount approved response
{
"transaction": {
"id": "tx_04"
},
"authorizedAmount": {
"value": 100,
"currencyCode": "USD"
},
"responseCode": "PARTIAL_AMOUNT_APPROVED"
}

Declined response

When you need to decline an AuthorizationEvent, your endpoint passes back an appropriate response code reflecting why your system declined the authorization:

Declined response
{
"transaction": {
"id": "tx_05"
},
"responseCode": "INSUFFICIENT_FUNDS"
}

Response codes

During collaborative authorization, when Highnote receives an authorization from the payment network, Highnote responds with one of three initial response codes:

  • APPROVED
  • PARTIAL_AMOUNT_APPROVED
  • DO_NOT_HONOR

You will only see a collaborative authorization request in your system if Highnote sends an APPROVED or PARTIAL_AMOUNT_APPROVED response. When your system responds to the collaborative authorization request, the resulting response code from Highnote's platform follows the pattern described in the following tables.

Approved response codes

The following table provides an overview of scenarios when Highnote provides an APPROVED response to a IssuerPreliminaryAuthorizationEvent:

Initial Highnote responseYour system's responseFinal Highnote platform response code
APPROVEDYour system returns an APPROVED response without authorizedAmount or with authorizedAmount equal to requestedAmountAPPROVED
APPROVEDYour system returns an APPROVED response with authorizedAmount less than requestedAmount and the POS supports partial approvalPARTIAL_AMOUNT_APPROVED
APPROVEDYour system returns an APPROVED response with authorizedAmount less than requestedAmount and POS does not support partial approvalDO_NOT_HONOR
APPROVEDYour system returns an APPROVED response with authorizedAmount more than requestedAmountDO_NOT_HONOR
APPROVEDYour system responds with an APPROVED response and authorizedAmount is not equal to requestedAmount and POS does not support partial approvalDO_NOT_HONOR
APPROVEDYour system returns a PARTIAL_AMOUNT_APPROVED response without authorizedAmountAPPROVED
APPROVEDYour system returns a PARTIAL_AMOUNT_APPROVED response with authorizedAmount equal to requestedAmountAPPROVED
APPROVEDYour system returns a PARTIAL_AMOUNT_APPROVED response with authorizedAmount more than requestedAmountDO_NOT_HONOR
APPROVEDYour system returns a PARTIAL_AMOUNT_APPROVED response with authorizedAmount less than requestedAmountPARTIAL_AMOUNT_APPROVED
APPROVEDYour system returns a PARTIAL_AMOUNT_APPROVED and authorizedAmount is not equal to requestedAmount and POS does not support partial approvalDO_NOT_HONOR
APPROVEDYour system returns a response with a different currency code than requestedAmount.currencyCodeDO_NOT_HONOR

Partial amount approved response codes

The following table provides an overview of scenarios when Highnote provides an PARTIAL_AMOUNT_APPROVED response to a IssuerPreliminaryAuthorizationEvent:

Initial Highnote responseYour system's responseFinal Highnote platform response code
PARTIAL_AMOUNT_APPROVEDYour system returns an APPROVED response without authorizedAmount or with authorizedAmount equal to requestedAmountPARTIAL_AMOUNT_APPROVED
PARTIAL_AMOUNT_APPROVEDYour system returns an APPROVED response with authorizedAmount less than requestedAmountPARTIAL_AMOUNT_APPROVED
PARTIAL_AMOUNT_APPROVEDYour system returns an APPROVED response with authorizedAmount more than requestedAmountDO_NOT_HONOR
PARTIAL_AMOUNT_APPROVEDYour system returns an PARTIAL_AMOUNT_APPROVED response without authorizedAmountPARTIAL_AMOUNT_APPROVED
PARTIAL_AMOUNT_APPROVEDYour system returns a PARTIAL_AMOUNT_APPROVED response with authorizedAmount equal to requestedAmountPARTIAL_AMOUNT_APPROVED
PARTIAL_AMOUNT_APPROVEDYour system returns a PARTIAL_AMOUNT_APPROVED response with authorizedAmount more than requestedAmountDO_NOT_HONOR
PARTIAL_AMOUNT_APPROVEDYour system returns a PARTIAL_AMOUNT_APPROVED response with authorizedAmount less than requestedAmountPARTIAL_AMOUNT_APPROVED
PARTIAL_AMOUNT_APPROVEDYour system returns a PARTIAL_AMOUNT_APPROVED response and authorizedAmount is not equal to requestedAmount and POS does not support partial approvalDO_NOT_HONOR
PARTIAL_AMOUNT_APPROVEDYour system returns a response with a different currency code than requestedAmount.currencyCodeDO_NOT_HONOR

Find collaborative authorization key

When you register a collaborative authorization endpoint, the API returns a secret key. If you need to retrieve this key again, you can query the CollaborativeAuthorizationEndpoint object to retrieve the signingKeys field.

Use the following query to retrieve a collaborative authorization endpoint's secret key:

CollaborativeAuthorizationEndpoint
Query
query CollaborativeAuthorizationEndpoint($id: ID!) {
node(id: $id) {
__typename
... on CollaborativeAuthorizationEndpoint {
id
signingKeys {
id
secret
createdAt
}
}
}
}
Variables
{
"id": "COLLABORATIVE_AUTHORIZATION_ENDPOINT_ID"
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"node": {
"__typename": "CollaborativeAuthorizationEndpoint",
"id": "COLLABORATIVE_AUTHORIZATION_ENDPOINT_ID",
"signingKeys": [
{
"id": "SECRET_KEY_ID",
"secret": "SECRET_KEY",
"createdAt": "2024-06-06T16:12:20.800Z"
}
]
}
},
"extensions": {
"requestId": "REQUEST_ID",
"rateLimit": {
"cost": 2,
"limit": 100000,
"remaining": 99998
}
}
}

Simulate collaborative authorization

Use the collaborative authorization simulation to test your endpoints in the Test environment. For more information, see Simulate Collaborative Authorization.