Skip to content
Last updated

This walkthrough validates authentication, catalog access, file upload, and result delivery in sandbox.

1. Prepare credentials

Obtain the sandbox API token, confirm the calling IP is allowlisted, and configure a public HTTPS webhook endpoint with Percents.

export PERCENTS_API_BASE='https://sandbox.percents.com'
export PERCENTS_API_TOKEN='tok_your_id:api_your_secret'

2. Read merchants and offers

curl --fail-with-body \
  --header "Authorization: token ${PERCENTS_API_TOKEN}" \
  "${PERCENTS_API_BASE}/api/v1/omni/merchant"

curl --fail-with-body \
  --header "Authorization: token ${PERCENTS_API_TOKEN}" \
  "${PERCENTS_API_BASE}/api/v1/omni/offer"

Persist merchant and offer UUIDs exactly as returned. Do not infer access to a merchant from its name.

3. Request a Plaid upload URL

curl --fail-with-body --get \
  --header "Authorization: token ${PERCENTS_API_TOKEN}" \
  --data-urlencode 'content=plaid-txn-stream' \
  --data-urlencode 'fileType=json' \
  --data-urlencode 'fileName=transactions-2026-08-10.json' \
  "${PERCENTS_API_BASE}/api/fileUpload"

The response contains a presigned URL that expires after 15 minutes:

{
  "url": "https://object-storage.example/presigned-upload"
}

4. Upload the file

curl --fail-with-body \
  --request PUT \
  --header 'Content-Type: application/json' \
  --data-binary @transactions.json \
  'PRESIGNED_URL_FROM_THE_PREVIOUS_RESPONSE'

Do not send the Percents API token to the presigned URL. The URL itself grants temporary permission to upload that single object.

5. Receive the result

Return a successful 2xx response after validating the webhook signature and durably recording the event. Process each webhookId idempotently.

The result is not delivered on a fixed schedule. Automated checks and human oversight must finish first. Contact Percents if no result webhook arrives within three business days after a successful file upload.