PineTree API

PineTree API

Launch payment sessions and connect checkout flows through one clean API.

Webhooks & Events

Send real-time payment updates to your app as transactions move through checkout.

A Seamless API Integration

PineTree API gives developers one clean way to manage separate payment rails, wallet logic, provider rules, and status handling, developers can connect through PineTree and build around a simpler, unified payment engine.

Preview
PineTree API
Create Payment Sessions
One Payment Engine
Real-Time Status
Built for Developers
PineTree API lets developers create payment sessions for hosted checkout, payment links, custom checkout buttons, merchant tools, and future commerce workflows. Your app can send the amount, currency, customer details, and return destination while PineTree prepares the payment experience behind the scenes.
Instead of building separate payment logic for every rail, PineTree API gives your platform one clean connection point. PineTree handles the supported payment networks, checkout flow, transaction lifecycle, and merchant-facing payment records through a unified payment engine.
PineTree API is designed around clear payment states like Waiting, Processing, Confirmed, Failed, and Expired. These statuses help your website, app, dashboard, receipt flow, or order system stay aligned as a transaction moves through checkout.
PineTree API is built to be simple for developers while keeping private infrastructure, provider logic, and backend payment details protected. Developers can integrate clean payment flows without needing to manage every network, wallet, processor, or transaction rule directly.

Built for the payment layer behind your product

PineTree API is designed to sit behind the checkout experience and handle the payment flow from start to finish. Developers can create sessions, send customers into a guided payment experience, track each transaction as it moves through its lifecycle, and return clean payment results back into their own app or merchant system.

PineTree API features available out of the box

Create Payment Sessions

  • Launch hosted or custom checkout flows
  • Send amount, currency, and payment details
  • Support payment links and checkout buttons
  • Build one API connection for digital payments

Unified Payment Engine

  • Connect to PineTree through one clean interface
  • Route checkout activity through supported rails
  • Reduce separate payment logic across networks
  • Keep provider complexity behind the scenes

Real-Time Payment Status

  • Track payments through clear lifecycle states
  • Use Waiting, Processing, Confirmed, Failed, and Expired
  • Update dashboards, receipts, and order flows
  • Keep customer and merchant screens aligned

Developer-Friendly Integration

  • Designed for websites, apps, and merchant tools
  • Simple structure for payment session creation
  • Works with hosted checkout and custom flows
  • Keeps private infrastructure and secrets protected

Documentation

Overview

PineTree API lets developers create checkout sessions, redirect customers to hosted checkout, retrieve payment status, verify signed webhook events, and reconcile payments across enabled payment rails.

Early access: PineTree Payments is currently in early access. API access, SDK packages, hosted checkout, and card-processing availability may require approved merchant access.

At a glance

Base URLhttps://app.pinetree-payments.com
API prefix/api/v1
Server authAuthorization: Bearer pt_live_*
Browser authX-PineTree-Public-Key: pk_live_*
Webhook schemapayments-v1
Crypto railssolana, base, bitcoin_lightning
Card railshift4 for approved merchants.
Fulfillment eventpayment.confirmed

Core flow

  1. Create a Checkout Session from your server using a secret API key.
  2. Redirect the customer to the returned checkoutUrl.
  3. The customer completes payment on an enabled crypto or card rail.
  4. PineTree sends a signed webhook event to your endpoint.
  5. Verify the webhook signature and deduplicate using PineTree-Event-Id.
  6. Fulfill the order only after payment.confirmed.

Fulfillment rule: Do not fulfill from the customer redirect alone. Failed, Expired, and Incomplete payments must never trigger fulfillment.

Quickstart

Create a checkout session server-side, redirect the customer, then fulfill only after a confirmed webhook.

1. Install the Node SDK

npm install @pinetreepayments/node

2. Create a checkout session

import { PineTree } from "@pinetreepayments/node"

const pinetree = new PineTree(process.env.PINETREE_API_KEY)

const session = await pinetree.checkout.sessions.create(
  {
    amount: 2500,
    currency: "USD",
    reference: "order_1042",
    customer: {
      email: "jane@example.com"
    },
    successUrl: "https://yoursite.com/paid",
    cancelUrl: "https://yoursite.com/cancel",
    metadata: {
      cartId: "cart_123"
    }
  },
  {
    idempotencyKey: "order_1042"
  }
)

res.redirect(session.checkoutUrl)

3. Verify webhooks before fulfillment

app.post(
  "/webhooks/pinetree",
  express.raw({ type: "application/json" }),
  async (req, res) => {
    let event

    try {
      event = pinetree.webhooks.constructEvent(
        req.body,
        req.headers,
        process.env.PINETREE_WEBHOOK_SECRET
      )
    } catch (error) {
      return res.status(400).send("Invalid webhook signature")
    }

    if (await alreadyProcessed(event.eventId)) {
      return res.json({ received: true, duplicate: true })
    }

    if (event.type === "payment.confirmed") {
      await fulfillOrder(event.data.object.reference)
      await markProcessed(event.eventId)
    }

    res.json({ received: true })
  }
)

Use express.raw() or the equivalent raw-body handler in your framework. Do not JSON-parse the request body before verifying the webhook signature.

Authentication

Use secret keys on your server. Use browser keys only for public checkout creation. Never expose secret API keys in frontend code.

CredentialPrefixWhere to use
Secret API keypt_live_*Server REST API calls and backend SDK usage.
Public browser keypk_live_*Browser checkout creation only.

Required server headers

Authorization: Bearer pt_live_your_api_key_here
Content-Type: application/json

Optional idempotency header

Idempotency-Key: order_1042

The Idempotency-Key header is optional but strongly recommended on POST /api/v1/checkout/sessions to prevent duplicate sessions on retries.

Browser checkout header

X-PineTree-Public-Key: pk_live_your_public_key_here
Content-Type: application/json

Security requirement: Never use pt_live_* keys in frontend JavaScript, browser code, mobile apps, or public repositories. Revoke any secret key that may have been exposed.

API Keys

Create narrowly scoped keys from the Developer area. Use the smallest scope set required for each integration. Secret keys are only shown once at creation time.

Recommended environment variables

PINETREE_API_KEY=pt_live_a1b2c3d4e5f6...
PINETREE_WEBHOOK_SECRET=whsec_...
NEXT_PUBLIC_PINETREE_PUBLIC_KEY=pk_live_...

Permissions

PermissionAllows
checkout.sessions:createCreate Checkout Sessions.
checkout.sessions:readList and retrieve Checkout Sessions.
checkout.sessions:writeCancel or expire Checkout Sessions.
payments:readRetrieve Payment objects.
checkout.links:createPayment-link creation where enabled.
webhooks:readList Webhook Deliveries.
webhooks:writeRetry Webhook Deliveries.

Best practices

  1. Grant only the scopes required for the integration.
  2. Use separate keys for different services or environments.
  3. Store secret keys in environment variables or a secrets manager.
  4. Monitor last-used timestamps in the dashboard.
  5. Revoke compromised or unused keys.

Checkout Sessions

Checkout Sessions create hosted payment pages. Create sessions from your server and fulfill orders only after confirmed webhook events.

checkoutUrl is opaque: Redirect customers directly to checkoutUrl. Do not construct or parse this URL manually.

POST /api/v1/checkout/sessions

Creates a hosted Checkout Session.

Authentication
Secret API key.
Required scope
checkout.sessions:create
Common errors
missing_api_key, missing_permission, invalid_amount, invalid_json, invalid_rails, idempotency_key_conflict

Request

{
  "amount": 2500,
  "currency": "USD",
  "reference": "order_1042",
  "customer": {
    "email": "jane@example.com"
  },
  "successUrl": "https://yoursite.com/paid",
  "cancelUrl": "https://yoursite.com/cancel",
  "metadata": {
    "cartId": "cart_123"
  },
  "rails": ["solana", "base"]
}

Response

{
  "id": "cs_01abc",
  "object": "checkout.session",
  "status": "open",
  "amount": 2500,
  "currency": "USD",
  "reference": "order_1042",
  "customer": {
    "email": "jane@example.com"
  },
  "metadata": {
    "cartId": "cart_123"
  },
  "checkoutUrl": "https://app.pinetree-payments.com/checkout/tok_01abc...",
  "paymentId": null,
  "supportedRails": ["solana", "base", "bitcoin_lightning"],
  "successUrl": "https://yoursite.com/paid",
  "cancelUrl": "https://yoursite.com/cancel",
  "createdAt": "2026-06-22T12:00:00.000Z",
  "expiresAt": "2026-06-23T12:00:00.000Z"
}

GET /api/v1/checkout/sessions

Lists Checkout Sessions.

Authentication
Secret API key.
Required scope
checkout.sessions:read or checkout.sessions:create
Query params
status, reference, limit, cursor, createdAfter, createdBefore

List response

{
  "object": "list",
  "data": [
    {
      "id": "cs_01abc",
      "object": "checkout.session",
      "status": "open"
    }
  ],
  "hasMore": true,
  "nextCursor": "eyJjcmVhdGVkQXQiOi..."
}

GET /api/v1/checkout/sessions/{id}

Retrieves a Checkout Session by ID.

Authentication
Secret API key.
Required scope
checkout.sessions:read or checkout.sessions:create

POST /api/v1/checkout/sessions/{id}/cancel

Cancels an open Checkout Session.

Authentication
Secret API key.
Required scope
checkout.sessions:write or checkout.sessions:create

POST /api/v1/checkout/sessions/{id}/expire

Expires an open Checkout Session.

Authentication
Secret API key.
Required scope
checkout.sessions:write or checkout.sessions:create

Browser Checkout

Browser checkout lets your frontend create a limited Checkout Session using a public browser key. Public keys are safe to embed in browser JavaScript, but they can only create checkout sessions.

Public key limitation: pk_live_* keys cannot retrieve payments, list webhook deliveries, retry webhooks, or access private merchant data.

POST /api/v1/browser/checkout/sessions

Creates a browser Checkout Session using X-PineTree-Public-Key.

Authentication
X-PineTree-Public-Key: pk_live_*
Common errors
invalid_public_key, origin_not_allowed, invalid_request

Fetch example

const response = await fetch(
  "https://app.pinetree-payments.com/api/v1/browser/checkout/sessions",
  {
    method: "POST",
    headers: {
      "X-PineTree-Public-Key": "pk_live_your_public_key_here",
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      amount: 2500,
      currency: "USD",
      reference: "order_1042",
      successUrl: window.location.origin + "/paid",
      cancelUrl: window.location.origin + "/cancel"
    })
  }
)

const session = await response.json()
window.location.href = session.checkoutUrl

JavaScript SDK

npm install @pinetreepayments/js
import { PineTreeJS } from "@pinetreepayments/js"

const ptjs = new PineTreeJS("pk_live_your_public_key_here")

const session = await ptjs.checkout.createSession({
  amount: 2500,
  currency: "USD",
  reference: "order_1042",
  successUrl: window.location.origin + "/paid",
  cancelUrl: window.location.origin + "/cancel"
})

ptjs.checkout.open(session)

React SDK

npm install @pinetreepayments/react
import { PineTreeProvider, PineTreeCheckoutButton } from "@pinetreepayments/react"

export function App() {
  return (
    <PineTreeProvider publicKey="pk_live_your_public_key_here">
      <CheckoutButton />
    </PineTreeProvider>
  )
}

function CheckoutButton() {
  return (
    <PineTreeCheckoutButton
      amount={2500}
      currency="USD"
      reference="order_1042"
      successUrl={window.location.origin + "/paid"}
      cancelUrl={window.location.origin + "/cancel"}
    >
      Pay with Crypto
    </PineTreeCheckoutButton>
  )
}

Payments

Use Payments for reconciliation, status lookup, and back-office workflows. Use webhook events as the primary fulfillment signal.

GET /api/v1/payments/{id}

Retrieves a Payment object.

Authentication
Secret API key.
Required scope
payments:read

Status naming: The visible state Confirmed maps to API status paid. Do not check for status === "confirmed". For polling, check status === "paid". For fulfillment, use payment.confirmed.

Payment object

FieldTypeDescription
idstringPineTree payment ID.
objectstringAlways payment.
statusstringCurrent payment status. paid means confirmed.
amountintegerAmount in cents.
currencystringFiat currency.
railstringPayment path, such as solana or base.
assetstringAsset paid by the customer, such as USDC, SOL, or BTC.
referencestringMerchant reference.
checkoutSessionIdstringBacking Checkout Session ID when present.
confirmedAtstringConfirmation timestamp when present.
metadataobjectPublic metadata from session creation.

Example response

{
  "id": "pay_01abc",
  "object": "payment",
  "status": "paid",
  "amount": 2500,
  "currency": "USD",
  "rail": "solana",
  "asset": "USDC",
  "reference": "order_1042",
  "checkoutSessionId": "cs_01abc",
  "confirmedAt": "2026-06-22T18:00:05.000Z",
  "metadata": {
    "cartId": "cart_123"
  }
}

Session Statuses

Checkout Session status tracks the aggregate lifecycle of the session. Session status and Payment status are related but not always identical.

StatusMeaningTerminal
openSession created and waiting for customer payment.No
processingCustomer submitted payment; awaiting network or provider confirmation.No
paidPayment confirmed. Session completed successfully.Yes
failedPayment attempt failed.Yes
expiredSession expired without confirmed payment.Yes
canceledSession canceled by merchant.Yes

For fulfillment, use payment.confirmed or checkout.session.completed webhooks. Use session retrieval for UI state and reconciliation.

Rails & Assets

Rails are payment paths. Assets are what the customer pays on that path. PineTree stores and returns both values separately.

RailAssets / CurrencyDescription
solanaSOL, USDCSolana Pay payments.
baseETH, USDCBase network payments.
bitcoin_lightningBTCLightning invoice payments.
shift4Card / USDCard payments for approved merchants. Contact support to enable.

Token-specific tracking

PineTree does not combine the rail and asset into one rail name. Instead, both values are stored and returned separately.

PaymentRailAssetDisplay
Solana SOLsolanaSOLSolana Pay · SOL
Solana USDCsolanaUSDCSolana Pay · USDC
Base ETHbaseETHBase Pay · ETH
Base USDCbaseUSDCBase Pay · USDC
Bitcoin Lightningbitcoin_lightningBTCLightning · BTC
Cardshift4USDCard · USD

Do not combine rail and asset: Use rail for the payment path and asset for what the customer paid.

Restrict rails on a session

{
  "amount": 2500,
  "currency": "USD",
  "rails": ["solana", "base"]
}

Card processing: Shift4 card processing is available for approved merchants. Stripe and Fluid Pay are early-access card provider paths and are not generally public card-processing rails yet.

Payment States

Confirmed is the successful visible payment state. Failed, Expired, and Incomplete are separate terminal outcomes.

Visible stateAPI statusWebhook eventTerminalFulfill?
Waitingopen / pendingpayment.pendingNoNo
Processingprocessingpayment.processingNoNo
Confirmedpaidpayment.confirmedYesYes
Failedfailedpayment.failedYesNo
Expiredexpiredpayment.expiredYesNo
Incompleteincompletepayment.incompleteYesNo

The visible state Confirmed maps to status: "paid" in the API Payment object. Do not check status === "confirmed".

Webhooks

Webhook deliveries are signed with PineTree headers. Verify the raw body before processing.

HeaderDescription
PineTree-SignatureHMAC-SHA256 signature. Verify before processing.
PineTree-TimestampTimestamp used in the signature and replay protection.
PineTree-Event-IdUnique event ID for deduplication.
PineTree-Event-Schemapayments-v1
PineTree-Webhook-VersionCompatibility header. Canonical schema header is PineTree-Event-Schema.

Signature formula

signed_payload = PineTree-Timestamp + "." + raw_request_body
expected_signature = HMAC_SHA256(webhook_secret, signed_payload)

Verification

const event = pinetree.webhooks.constructEvent(
  req.body,
  req.headers,
  process.env.PINETREE_WEBHOOK_SECRET
)

Use raw request body verification. Return 2xx only after durable processing. PineTree delivers events at least once, so store PineTree-Event-Id and deduplicate.

Webhook Payload

Every PineTree webhook is delivered as a JSON object with a standard payments-v1 envelope.

Event envelope

{
  "eventId": "evt_01abc",
  "object": "event",
  "type": "payment.confirmed",
  "schema": "payments-v1",
  "createdAt": "2026-06-22T18:00:00.000Z",
  "livemode": true,
  "data": {
    "object": {
      "id": "pay_01abc",
      "object": "payment",
      "status": "paid",
      "network": "solana",
      "amount": 2500,
      "currency": "USD",
      "reference": "order_1042",
      "confirmedAt": "2026-06-22T18:00:05.000Z",
      "metadata": {
        "cartId": "cart_123"
      }
    }
  }
}

network vs rail: Webhook payment events use network for the rail identifier. The REST Payment object uses rail for the same concept. Use event.data.object.network inside webhook handlers.

Webhook Events

Implemented merchant webhook events in the payments-v1 schema.

EventObjectWhen it fires
payment.createdpaymentPayment object created.
payment.pendingpaymentWaiting for customer or network action.
payment.processingpaymentPayment detected, awaiting confirmation.
payment.confirmedpaymentPayment completed. Fulfill the order.
payment.failedpaymentPayment failed.
payment.expiredpaymentPayment timed out.
payment.canceledpaymentPayment canceled.
payment.incompletepaymentCustomer abandoned or no funds were sent.
payment.refundedpaymentPayment refunded.
checkout.session.createdcheckout.sessionCheckout Session created.
checkout.session.processingcheckout.sessionCheckout Session payment in progress.
checkout.session.completedcheckout.sessionCheckout Session payment confirmed.
checkout.session.failedcheckout.sessionCheckout Session payment failed.
checkout.session.expiredcheckout.sessionCheckout Session expired.
checkout.session.canceledcheckout.sessionCheckout Session canceled.
payment_link.createdpayment_linkPayment link created.
payment_link.disabledpayment_linkPayment link disabled.
payment_link.expiredpayment_linkPayment link expired.

Use the canonical event names above for new integrations.

Webhook Deliveries

Use Webhook Deliveries to inspect delivery history and retry failed events.

GET /api/v1/webhook-deliveries

Lists Webhook Deliveries.

Authentication
Secret API key.
Required scope
webhooks:read
Query params
status, eventType, limit, cursor

POST /api/v1/webhook-deliveries/{id}/retry

Retries a failed Webhook Delivery.

Authentication
Secret API key.
Required scope
webhooks:write

Delivery statuses

StatusDescription
pendingQueued for delivery or retry.
deliveredEndpoint returned a 2xx response.
failedLast delivery attempt failed.
dead_letterAll retry attempts exhausted. Requires attention or manual retry.

Retry schedule

AttemptDelay before retry
160 seconds
2120 seconds
3240 seconds
4480 seconds
5960 seconds
61,800 seconds
7–103,600 seconds
After 10dead_letter

Node SDK retry

const delivery = await pinetree.webhookDeliveries.retry("wdel_01abc")
console.log(delivery.status)

Errors

Errors return a consistent JSON structure with a type, code, message, and request ID.

{
  "error": {
    "type": "authentication_error",
    "code": "missing_api_key",
    "message": "A PineTree API key is required.",
    "requestId": "req_01abc"
  }
}
TypeStatusMeaning
authentication_error401Missing or invalid key.
authorization_error403Key lacks required permission.
invalid_request_error400Malformed request.
idempotency_error409Idempotency conflict.
not_found_error404Object does not exist or is not accessible.
api_error500PineTree service error.

Common error codes

CodeMeaning
missing_api_keyNo Authorization header provided.
invalid_api_keyKey not found, revoked, or wrong format.
missing_permissionKey does not have the required scope.
invalid_amountAmount is missing, zero, or invalid.
invalid_public_keyBrowser public key is invalid or revoked.
checkout_session_not_foundNo session found for the provided ID.
payment_not_foundNo payment found for the provided ID.
webhook_delivery_not_foundNo delivery found for the provided ID.
idempotency_key_conflictSame key used with a different request body.
idempotency_request_in_progressRequest with this key is still in flight.

Idempotency

Use idempotency keys to safely retry Checkout Session creation without duplicate sessions.

REST example

POST /api/v1/checkout/sessions HTTP/1.1
Authorization: Bearer pt_live_...
Content-Type: application/json
Idempotency-Key: order_1042

{
  "amount": 2500,
  "currency": "USD",
  "reference": "order_1042"
}

Node SDK example

const session = await pinetree.checkout.sessions.create(
  {
    amount: 2500,
    currency: "USD",
    reference: "order_1042"
  },
  {
    idempotencyKey: "order_1042"
  }
)
ScenarioResult
Same key and same bodyReturns original session.
Same key and different bodyReturns idempotency_key_conflict.
Request still in progressReturns idempotency_request_in_progress.

Use a stable, unique value per order. Do not reuse the same idempotency key for different orders.

SDKs

Use the Node SDK on servers, the JavaScript SDK in browser flows, and the React SDK for checkout components.

SDK packages are available to approved early-access merchants. Contact info@pinetree-payments.com for access.

Node SDK

npm install @pinetreepayments/node
import { PineTree } from "@pinetreepayments/node"

const pinetree = new PineTree(process.env.PINETREE_API_KEY)

const session = await pinetree.checkout.sessions.create({
  amount: 2500,
  currency: "USD",
  reference: "order_1042"
})

const payment = await pinetree.payments.retrieve("pay_01abc")

const deliveries = await pinetree.webhookDeliveries.list({
  status: "failed"
})

await pinetree.webhookDeliveries.retry("wdel_01abc")

JavaScript SDK

npm install @pinetreepayments/js

React SDK

npm install @pinetreepayments/react

Testing

PineTree currently uses live keys only. There is no separate sandbox or test-mode key prefix. Test with small live amounts and an HTTPS tunnel for local webhook development.

ngrok http 3000

# Register your HTTPS URL in Developer - Webhooks
https://abc123.ngrok-free.app/webhooks/pinetree

Testing checklist

  1. Create a checkout session.
  2. Complete a small live payment.
  3. Verify payment.confirmed arrives.
  4. Replay the same event and confirm deduplication.
  5. Test failed, expired, and incomplete paths.
  6. Temporarily return 500 and verify webhook retry behavior.

Go Live

Complete these checks before accepting real payments at volume.

AreaChecklist
API keysSecret key created with minimal permissions and stored server-side. Public key used only for browser checkout.
WebhooksHTTPS endpoint configured, raw-body verification enabled, duplicate event handling in place.
Payment flowsConfirmed payments fulfill orders. Failed, Expired, and Incomplete payments do not fulfill.
RailsEnabled payment rails are configured and tested with small live amounts.
CardsCard processing enabled only after approved provider onboarding.
SupportTeam knows where to find requestId, Checkout Session ID, Payment ID, and webhook Event ID.

Do not fulfill based on the customer redirect alone. Always rely on verified webhook events.

Not Yet Supported

The following capabilities are planned for future PineTree API versions. They are not required for the current hosted checkout and webhook integration flow.

CapabilityNotes
Refund APIRefunds are currently processed through the merchant dashboard. A REST endpoint is planned.
Payout / settlement APISettlement preferences are configured in the dashboard. A programmatic API is planned.
Disputes APIDispute management will be available after card processing is generally available.
Sandbox / test-mode keysPineTree currently uses live keys only. A dedicated test environment is planned.
Advanced reporting APIReports are currently available from the dashboard. A REST reporting endpoint is planned.
Stripe card processingEarly access. Contact support for access.
Fluid Pay card processingEarly access. Contact support for access.
Recurring billingOne-time checkout sessions are supported. Subscriptions are on the roadmap.
Customer objectsCustomer data currently lives on sessions and payments as metadata.
Invoice APINot yet available.

Support

Contact PineTree for integration help, API access, SDK issues, and merchant onboarding questions.

Emailinfo@pinetree-payments.com
Phone417-718-2692

Include this in support requests

  1. Merchant account email or merchant ID.
  2. API endpoint used.
  3. requestId from the error response.
  4. Checkout Session ID.
  5. Payment ID.
  6. Webhook Event ID.
  7. Error type and code.
  8. Approximate timestamp in UTC.