Skip to main content

Check Payment

Overview

Contact Highnote

To enable Check Payment, contact your Highnote implementation team or support@highnote.com.

Subscribers can enable their systems to let account holders send payments by check. Checks are funded by a FinancialAccount. Checks greater than $2,000 USD must have a signature of the Primary Authorized Person linked to the FinancialAccount.

Attaching a signature to a FinancialAccount

tip

Only checks greater than or equal to $2,000 require a signature.

Signatures must be saved in PDF format and attached to a FinancialAccount. High-level steps are:

  1. Create an upload session to attach the signature to a FinancialAccount.
  2. Upload the signature to Highnote with either the Document Upload SDK or the Highnote GraphQL API.

Create check payment upload session

To begin, create a check payment document upload session to associate a signature with a FinancialAccount.

CreateCheckPaymentDocumentUploadSession
Query
mutation CreateCheckPaymentDocumentUploadSession(
$input: CreateCheckPaymentDocumentUploadSessionInput!
) {
createCheckPaymentDocumentUploadSession(input: $input) {
__typename
... on DocumentUploadSession {
id
}
}
}
Variables
{
  "input": {
    "financialAccountId": "ac_ba22446a041287274d81af25bb83eeba46b1",
    "documentTypes": [
      "ACCOUNT_HOLDER_SIGNATURE"
    ]
  }
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"createSignatureUploadSession": {
"__typename": "CheckPaymentDocumentUploadSession",
"id": "du_22chkcd093a56f66b864ce09e0d3f3296750190"
}
}
}

Upload signature to Highnote

Next, upload the signature to Hignote. Signatures can be uploaded to Highnote one of two ways:

  • The Document Upload SDK lets users upload their own signature file.
  • The Highnote GraphQL API can upload a signature if the file is already present.

If you use the Highnote GraphQL API, the document upload process consists of the following steps:

  1. Optional - Generate a client token.
  2. Start a document upload session to Highnote
  3. Create a document upload link
  4. Upload the signature with the upload link.
  5. End the document upload session

Lifecycle of Document Upload Status

Start document upload session

info

For compliance reasons, you must generate a client token to make requests directly from your client if you are not using a server or do not have access to one. See Client Tokens.

The Start mutation generates a session URL. Upload sessions expire 30 days from creation; and each session notifies you of any requirements your system needs to enforce to upload the file.

Use the following mutation to start a document upload session:

StartDocumentUploadSession
Query
mutation StartDocumentUploadSession($input: StartDocumentUploadSessionInput!) {
startDocumentUploadSession(input: $input) {
... on CheckPaymentDocumentUploadSession {
id
status
}
}
}
Variables
{
  "input": {
    "documentUploadSessionId": "my-signature-upload-session"
  }
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"startDocumentUploadSession": {
"id": "start-document-upload-session-id",
"status": "INITIATED"
}
}
}
you have five minutes

Document upload links expire 5 minutes after creation.

Each upload link created with this mutation represents a single upload file. If, for example, you are required to upload two signature files, you must create a unique link for each.

When creating upload links, the document upload session status transitions to PENDING. You can use the uploadURL field in the mutation's response to stream the document upload.

To create a document upload link, use the DOCUMENT_UPLOAD_SESSION_ID from the startDocumentUploadSession response for this mutation's variable field:

Query
mutation CreateDocumentUploadLink($input: CreateDocumentUploadLinkInput!) {
createDocumentUploadLink(input: $input) {
... on DocumentUploadLink {
id
uploadUrl
}
}
}
Variables
{
  "input": {
    "documentUploadSessionId": "my-signature-upload-session",
    "documentType": "ACCOUNT_HOLDER_SIGNATURE"
  }
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"createDocumentUploadLink": {
"id": "signature-upload-link-id",
"uploadUrl": "https://storage.googleapis.upload-to-bucket"
}
}
}

End the document upload session

After the signature has been uploaded, you can end the document upload session. When ending a session, the session status transitions to SUBMITTED and no other actions can be taken. If more documentation is required, a new session must be started to upload the additional documents.

Use the following mutation to end a document upload session:

EndDocumentUploadSession
Query
mutation EndDocumentUploadSession($input: EndDocumentUploadSessionInput!) {
endDocumentUploadSession(input: $input) {
... on DocumentUploadSession {
status
}
}
}
Variables
{
  "input": {
    "documentUploadSessionId": "my-signature-upload-session"
  }
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"endDocumentUploadSession": {
"status": "SUBMITTED"
}
}
}

Initiate a physical check payment

note

Refer to the check image below to see how physical check items map to API fields.

To begin a check payment, call the initiatePhysicalCheckPayment mutation using a sufficiently funded FinancialAccount and a recipient's name and an address (ideally, a validatedAddressTokenId).

Address Validation

Before initiating a check payment, Highnote recommends that you utilize the Address Validation service (below) to ensure the recipient's address is correctly formatted and verified.

Steps are:

  1. Call validateAddress to check if the check payment address is valid.
  2. From the response, copy validatedAddressTokenId representing the validated address.
  3. Call InitiatePhysicalCheckPayment with the response token Id.

Shipping Method

You can specify the type of check and the shipping method when initiating a check payment. The check funding process takes 2-3 business days to complete, in addition to the stated mailing times.

The following shipping methods are supported:

MethodTimingCarrier
STANDARD2-5 business daysUSPS
CERTIFIED2-5 business daysUSPS
EXPEDITED2 daysFEDEX or UPS
OVERNIGHTNext dayFEDEX or UPS

Validate check payment address

You can validate the check payment address using the validateAddress mutation. This mutation validates addresses using a CASS-certified service to ensure it is properly formatted to reduce possible shipping delays or returns.

The Highnote API returns an AddressValidationResult response with a validated address token, or an error message explaining why the address is invalid.

ValidateAddress
Query
mutation validateAddress($input: ValidateAddressInput!) {
validateAddress(input: $input) {
__typename
... on AddressValidationResult {
outcome {
__typename
... on AddressValidatedWithChangesResult {
token {
id
}
}
... on AddressValidatedResult {
token {
id
}
}
}
}
}
}
Variables
{
  "input": {
    "idempotencyKey": "idempotency-key",
    "address": {
      "streetAddress": "24 WILLIE MAYS PLZ",
      "extendedAddress": "",
      "postalCode": "94107-2134",
      "region": "CA",
      "locality": "SAN FRANCISCO",
      "countryCodeAlpha3": "USA"
    }
  }
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"validateAddress": {
"__typename": "AddressValidationResult",
"outcome": {
"__typename": "AddressValidatedResult",
"token": {
"id": "tkvad_1"
}
}
}
}
}

Initiate physical check payment with validated address token

Use the following mutation to initiate a check payment with a validatedAddressTokenId:

InitiatePhysicalCheckPayment
Query
mutation validateAddress($input: ValidateAddressInput!) {
validateAddress(input: $input) {
__typename
... on AddressValidationResult {
outcome {
__typename
... on AddressValidatedWithChangesResult {
token {
id
}
}
... on AddressValidatedResult {
token {
id
}
}
}
}
}
}
Variables
{
  "input": {
    "idempotencyKey": "idempotency-key",
    "address": {
      "streetAddress": "24 WILLIE MAYS PLZ",
      "extendedAddress": "",
      "postalCode": "94107-2134",
      "region": "CA",
      "locality": "SAN FRANCISCO",
      "countryCodeAlpha3": "USA"
    }
  }
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"validateAddress": {
"__typename": "AddressValidationResult",
"outcome": {
"__typename": "AddressValidatedResult",
"token": {
"id": "tkvad_1"
}
}
}
}
}

Initiate physical check payment with unvalidated address

While not recommended, you can use the following mutation to initiate a check payment with an unvalidated address.

To use a validated address instead, see Initiate physical check payment with validated address token (above).

InitiatePhysicalCheckPayment
Query
mutation InitiatePhysicalCheckPayment(
$input: InitiatePhysicalCheckPaymentInput!
) {
initiatePhysicalCheckPayment(input: $input) {
__typename
... on CheckPayment {
id
amount {
__typename
value
currencyCode
decimalPlaces
}
recipient {
__typename
name
address {
__typename
streetAddress
extendedAddress
postalCode
region
locality
countryCodeAlpha3
}
}
checkType
shippingTime
status
events {
__typename
id
type
}
}
}
}
Variables
{
  "input": {
    "financialAccountId": "ac_1",
    "amount": {
      "value": 100,
      "currencyCode": "USD"
    },
    "recipient": {
      "name": "John Doe",
      "validatedAddressTokenId": "tkvad_1"
    },
    "shippingTime": "STANDARD"
  }
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"initiatePhysicalCheckPayment": {
"__typename": "CheckPayment",
"id": "eftck_1",
"amount": {
"__typename": "Amount",
"value": 100,
"currencyCode": "USD",
"decimalPlaces": 2
},
"recipient": {
"__typename": "CheckPaymentRecipient",
"name": "John Doe",
"address": {
"__typename": "Address",
"streetAddress": "123 Main St",
"extendedAddress": "Apt 1",
"postalCode": "12345",
"region": "CA",
"locality": "San Francisco",
"countryCodeAlpha3": "USA"
}
},
"checkType": "PHYSICAL",
"shippingTime": "STANDARD",
"status": "PENDING",
"events": [
{
"__typename": "CheckPaymentEvent",
"id": "eftct_1",
"type": "FUNDING_PENDING"
}
]
}
}
}

Check payment event types

Payments made by check follow an event lifecycle with the possible types outlined below. Your platform receives a notification event as each check payment transitions to a new type.

The Highnote transaction event and notification event for all check payment types is the CheckPaymentEvent.

For typical "happy path" check payments, subscribers can expect to receive events in the order as presented in the following table:

#Event TypeDescription
Happy path order of events
1PENDING_PROCESSING_BY_HIGHNOTEThe check has been initiated and is pending processing by Highnote.
2PROCESSING_BY_HIGHNOTEThe check is being processed and validated by Highnote. It is being checked for funds availability and risk analysis.
3PROCESSED_BY_HIGHNOTEThe check has been processed by Highnote and is awaiting funding to our check provider.
4FUNDING_PENDINGThe check has been picked up by the daily check cutoff window for funding.
5FUNDING_STARTEDThe check funding to our external check provider has been initiated.
6FUNDING_COMPLETEDThe check has been funded and is pending disbursement.
7FUNDING_DISBURSEDThe funds have been disbursed to external accounts.
8PRINTEDThe check has been printed.
9PENDING_SHIPMENTThe check has been printed and is pending shipment.
10SHIPPEDThe check has been shipped.
11PAIDThe check has been deposited by the recipient.
12COMPLETEDThe check has been deposited by the recipient and the ledgers against the FinancialAccount have been reconciled.
Alternative events
ON_RISK_HOLDThe check has been put on hold for risk assessment.
VOIDEDThe check has been voided.
FAILEDThe check has failed. The reason for the failure is included in the event.
REVERSAL_INITIATEDThe check has been reversed due to voiding or failure.
REVERSAL_COMPLETEDThe check reversal has been completed.

Query for check payments

Use the following mutations to query for one check payment or list multiple check payments.

View a check payment

Use the node query to query for a CheckPayment.

QueryCheckPayment
Query
query QueryCheckPayment($id: ID!) {
node(id: $id) {
__typename
... on CheckPayment {
id
amount {
value
decimalPlaces
currencyCode
}
recipient {
__typename
name
address {
__typename
streetAddress
extendedAddress
postalCode
region
locality
countryCodeAlpha3
}
}
checkType
shippingTime
status
failureReason
events {
__typename
id
type
}
}
}
}
Variables
{
"id": "eftck_1"
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"node": {
"__typename": "CheckPayment",
"id": "eftck_1",
"amount": {
"value": 1,
"decimalPlaces": 2,
"currencyCode": "USD"
},
"recipient": {
"__typename": "CheckPaymentRecipient",
"name": "John Doe",
"address": {
"__typename": "Address",
"streetAddress": "123 Main St",
"extendedAddress": "Apt 1",
"postalCode": "12345",
"region": "CA",
"locality": "San Francisco",
"countryCodeAlpha3": "USA"
}
},
"checkType": "PHYSICAL",
"shippingTime": "STANDARD",
"status": "FUNDING_PENDING",
"failureReason": null,
"events": [
{
"__typename": "CheckPaymentEvent",
"id": "eftct_246g65s8hvkjjm139o3gep6i7wp1sb6nva",
"type": "FUNDING_PENDING"
},
{
"__typename": "CheckPaymentEvent",
"id": "eftct_246g65s8hvkjjm139o3gep6i7wp1sb6nva",
"type": "PENDING_PROCESSING_BY_HIGHNOTE"
}
]
}
}
}

List check payments

Use the FinancialAccount.checkPayments query to return a list of CheckPayments. The query can return all check-related fields including the check image.

ListCheckPayments
Query
query ListCheckPayments($financialAccountId: ID!, $first: Int, $after: String) {
node(id: $financialAccountId) {
__typename
... on FinancialAccount {
checkPayments(first: $first, after: $after) {
__typename
... on CheckPaymentsConnection {
edges {
node {
id
amount {
__typename
value
currencyCode
decimalPlaces
}
recipient {
__typename
name
address {
__typename
streetAddress
extendedAddress
postalCode
region
locality
countryCodeAlpha3
}
}
checkType
shippingTime
status
events {
__typename
id
type
}
}
}
}
}
}
}
}
Variables
{
"financialAccountId": "ac_1",
"first": 20
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"node": {
"__typename": "FinancialAccount",
"searchCheckPayments": {
"__typename": "SearchCheckPaymentsConnection",
"edges": [
{
"node": {
"id": "eftck_1",
"amount": {
"__typename": "Amount",
"value": 100,
"currencyCode": "USD",
"decimalPlaces": 2
},
"recipient": {
"__typename": "CheckPaymentRecipient",
"name": "John Doe",
"address": {
"__typename": "Address",
"streetAddress": "123 Main St",
"extendedAddress": "Apt 1",
"postalCode": "12345",
"region": "CA",
"locality": "San Francisco",
"countryCodeAlpha3": "USA"
}
},
"checkType": "PHYSICAL",
"shippingTime": "STANDARD",
"status": "PENDING",
"events": [
{
"__typename": "CheckPaymentEvent",
"id": "eftct_1",
"type": "FUNDING_PENDING"
}
]
}
}
]
}
}
}
}

Simulate check payment event changes

info

Simulating an event is an asynchronous action. Highnote sends a webhook event and adds the event shortly after the simulation.

Use the SimulateCheckPaymentEvent mutation below to test different Check Payment event types.

In the Test environment, a Check Payment does not progress past the FUNDING_PENDING event type in the Check Payment workflow. But you can simulate the progress of a check payment by triggering the mutation with a specific event type. For example, eftck_1 triggers a FUNDING_STARTED event.

You can only actively simulate 5 event types (below), and only in the given order. The Highnote platform applies the other event types as appropriate. For example, when you simulate paying out by check, you trigger the PAID event type. Highnote then moves it to COMPLETED.

Sim OrderEvent TypeDescription
1FUNDING_STARTEDThe check funding to our external check provider has been initiated.
2FUNDING_COMPLETEDThe check has been funded and is pending disbursement.
3FUNDING_DISBURSEDThe funds have been disbursed to external accounts.
4SHIPPEDThe check has been shipped.
5PAIDThe check has been deposited by the recipient.
SimulateCheckPaymentEvent
Query
mutation InitiatePhysicalCheckPayment(
$input: InitiatePhysicalCheckPaymentInput!
) {
initiatePhysicalCheckPayment(input: $input) {
__typename
... on CheckPayment {
id
amount {
__typename
value
currencyCode
decimalPlaces
}
recipient {
__typename
name
address {
__typename
streetAddress
extendedAddress
postalCode
region
locality
countryCodeAlpha3
}
}
checkType
shippingTime
status
events {
__typename
id
type
}
}
}
}
Variables
{
  "input": {
    "financialAccountId": "ac_1",
    "amount": {
      "value": 100,
      "currencyCode": "USD"
    },
    "recipient": {
      "name": "John Doe",
      "address": {
        "streetAddress": "123 Main St",
        "extendedAddress": "Apt 1",
        "postalCode": "12345",
        "region": "CA",
        "locality": "San Francisco",
        "countryCodeAlpha3": "USA"
      }
    },
    "shippingTime": "STANDARD"
  }
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
Result
{
"data": {
"initiatePhysicalCheckPayment": {
"__typename": "CheckPayment",
"id": "eftck_1",
"amount": {
"__typename": "Amount",
"value": 100,
"currencyCode": "USD",
"decimalPlaces": 2
},
"recipient": {
"__typename": "CheckPaymentRecipient",
"name": "John Doe",
"address": {
"__typename": "Address",
"streetAddress": "123 Main St",
"extendedAddress": "Apt 1",
"postalCode": "12345",
"region": "CA",
"locality": "San Francisco",
"countryCodeAlpha3": "USA"
}
},
"checkType": "PHYSICAL",
"shippingTime": "STANDARD",
"status": "PENDING",
"events": [
{
"__typename": "CheckPaymentEvent",
"id": "eftct_1",
"type": "FUNDING_PENDING"
}
]
}
}
}

Check image

The following image maps API fields to the physical check:

Check Payment Example

  1. Business account holder legalBusinessName or Personal account holder familyName and givenName
  2. amount : InitiatePhysicalCheckPaymentInput
  3. recipient : InitiatePhysicalCheckPaymentInput
  4. memo : InitiatePhysicalCheckPaymentInput
  5. Uploaded signature