API Docs
API ReferenceAPI Integration Guide

API Integration Guide

Use this guide when you want to integrate the Paychtec APIs directly from your application backend.

Working with an LLM agent? Ask it to read this file first, then implement the backend API calls, payloads, webhook verification, retries, and order-state updates according to this guide.

Related integration guides:

LLM Agent Prompt

Read the API integration guide at https://docs.v2.paychtec.com/docs/INTEGRATION_API and, if the checkout uses the JavaScript SDK, also read https://docs.v2.paychtec.com/docs/INTEGRATION_SDK. Build a merchant API integration only. Keep secret keys on the server, use the sandbox API first, send the payloads documented in the Payload Reference section, use order_details for order contents, do not invent customer_id values for POST /payments, add idempotency keys for retryable mutations, verify webhook signatures, and update order state from webhooks.

Scope

This guide is for merchants integrating payments into their own application.

Use merchant resources:

  • Secret API keys for server-side API calls.
  • profile_id for the merchant business profile used on payments.
  • customer_id, payment_id, refund_id, and similar IDs for merchant-owned records.
  • Webhooks for final payment, refund, dispute, payout, and subscription state.

Environments

Use sandbox while building and testing:

https://api.sandbox.paychtec.com

Use production only after your integration has passed testing:

https://api.v2.paychtec.com

Sandbox keys usually start with snd_; production keys usually start with prd_. Never use production credentials for tests unless you intend to create real transactions.

Required Headers

Content-Type: application/json
api-key: snd_YOUR_API_KEY

For retryable POST, PUT, or DELETE requests, include a stable idempotency key:

X-Idempotency-Key: order_123_attempt_1

Use the same idempotency key when retrying the same logical operation. Do not generate a new key for each retry.

  1. Create a server-side API client. Store the secret API key in server environment variables and centralize request headers, base URL selection, timeout handling, and response parsing.

  2. Create or retrieve a customer. Use customers when you need saved payment methods, subscriptions, repeat purchases, or clean reconciliation. If you pass customer_id to POST /payments, it must be an existing Paychtec customer ID returned by the Customers API. Do not invent a local customer ID and send it directly on a payment.

  3. Create a payment. Use POST /payments. Send amount in the smallest currency unit, the ISO currency code, profile_id, and your merchant metadata. For a simple one-off payment, omit customer_id and send customer details directly on the payment payload: email, name, phone, and phone_country_code. Use order_details for order contents. Do not send items, line_items, or cart_items.

  4. Confirm the payment. Use confirm: true in the create payload for a one-step flow, or call POST /payments/:payment_id/confirm in a two-step flow.

  5. Handle redirects and next actions. Some methods require 3DS, wallet authorization, bank redirects, or asynchronous processing.

  6. Verify webhooks. Webhooks should update local order and ledger state. Treat webhooks as the source of truth for asynchronous outcomes.

  7. Capture, cancel, or refund. Capture manual payments after fulfillment, cancel abandoned authorizations, and refund settled payments with retry-safe refund_id values.

Payload Reference

Common mistakes: Do not send items; use order_details. Do not invent customer_id. Do not expose secret API keys in the browser. Do not update final order state from the browser response alone; use webhooks as the source of truth.

Create Customer

POST /customers

Use this payload when creating a reusable customer profile.

{
  "customer_id": "cus_acme_42",
  "email": "customer@example.com",
  "name": "Jane Customer",
  "phone": "6502530000",
  "phone_country_code": "+1",
  "description": "Customer from checkout",
  "address": {
    "line1": "1600 Amphitheatre Parkway",
    "city": "Mountain View",
    "state": "CA",
    "zip": "94043",
    "country": "US",
    "first_name": "Jane",
    "last_name": "Customer"
  },
  "metadata": {
    "internal_customer_id": "42"
  }
}

Important fields:

FieldRequiredNotes
customer_idNoOptional merchant-supplied customer identifier for POST /customers. Once created, use the returned Paychtec customer ID on future payment requests.
emailNoRecommended for receipts, fraud checks, 3DS, subscriptions, and BNPL.
addressNoCan be reused as default billing details.
metadataNoStore non-sensitive merchant references only.

Create Payment

POST /payments

Use this one-step payload when your backend is allowed to send payment method details and should authorize immediately. For a simple one-off payment, omit customer_id and provide email, name, phone, and phone_country_code directly on the payment payload. Only send customer_id when you have first created or retrieved the customer through the Customers API and are passing the returned Paychtec customer ID. Order contents must be sent as order_details; do not use items, line_items, or cart_items. Include billing on the request that sends payment_method_data: on POST /payments for one-step confirmation, or on POST /payments/:payment_id/confirm for two-step confirmation.

{
  "amount": 6540,
  "currency": "USD",
  "profile_id": "YOUR_PROFILE_ID",
  "payment_id": "pay_order_123",
  "confirm": true,
  "capture_method": "automatic",
  "authentication_type": "three_ds",
  "return_url": "https://example.com/payment-return",
  "email": "customer@example.com",
  "name": "Jane Customer",
  "phone": "6502530000",
  "phone_country_code": "+1",
  "payment_method": "card",
  "payment_method_type": "credit",
  "payment_method_data": {
    "card": {
      "card_number": "4242424242424242",
      "card_exp_month": "12",
      "card_exp_year": "2028",
      "card_cvc": "123",
      "card_holder_name": "Jane Customer"
    }
  },
  "billing": {
    "address": {
      "line1": "1600 Amphitheatre Parkway",
      "city": "Mountain View",
      "state": "CA",
      "zip": "94043",
      "country": "US",
      "first_name": "Jane",
      "last_name": "Customer"
    },
    "phone": {
      "number": "6502530000",
      "country_code": "+1"
    }
  },
  "browser_info": {
    "ip_address": "203.0.113.42",
    "user_agent": "Mozilla/5.0",
    "accept_header": "text/html",
    "language": "en-US",
    "color_depth": 24,
    "screen_height": 1080,
    "screen_width": 1920,
    "time_zone": -300,
    "java_enabled": false,
    "java_script_enabled": true
  },
  "order_details": [
    {
      "name": "Premium plan",
      "quantity": 1,
      "amount": 6540,
      "currency": "USD"
    }
  ],
  "metadata": {
    "order_id": "order_123",
    "cart_id": "cart_456"
  }
}

Important fields:

FieldRequiredNotes
amountYesSmallest currency unit, such as cents for USD.
currencyYesThree-letter ISO currency code.
profile_idYesMerchant business profile used for the payment.
payment_idNoRecommended for merchant-side reconciliation and idempotent retries.
customer_idNoMust be an existing Paychtec customer ID returned by the Customers API. Do not generate a local customer ID and send it directly to POST /payments. For one-off payments, omit this field and send customer details directly on the payment payload.
confirmNoSet true for one-step authorization; set false for two-step flow.
emailRecommendedCustomer email for receipts, fraud checks, 3DS, and asynchronous payment methods.
nameRecommendedCustomer name for payment risk checks.
phoneRecommendedCustomer phone number without country code.
phone_country_codeRecommendedPhone country code, such as +1.
payment_methodConditionalRequired when confirming in the same request.
payment_method_typeConditionalRequired for many payment method categories.
payment_method_dataConditionalRequired when confirming with direct payment details.
billingYesRequired billing address and phone details for the payer. Include it on the request that sends payment_method_data.
return_urlConditionalRequired for redirect, wallet, bank redirect, and hosted checkout flows.
order_detailsRecommendedOrder contents for the payment. Use this field name; do not send items, line_items, or cart_items.
browser_infoRecommendedStrongly recommended for card payments and 3DS.
metadataNoStore order references, not secrets or raw card data.

If your flow needs customer_id, call POST /customers or GET /customers/:customer_id first, then pass the returned Paychtec customer ID to POST /payments.

Minimal One-Step Sandbox Payment

This example creates and confirms a card payment in one request without a reusable customer record.

curl -X POST 'https://api.sandbox.paychtec.com/payments' \  -H "Content-Type: application/json" \  -H "api-key: snd_YOUR_API_KEY" \  -H "X-Idempotency-Key: order_123_attempt_1" \  -d '{"amount": 6540,"currency": "USD","profile_id": "YOUR_PROFILE_ID","payment_id": "pay_order_123","confirm": true,"capture_method": "automatic","authentication_type": "three_ds","return_url": "https://example.com/payment-return","email": "customer@example.com","name": "Jane Customer","phone": "6502530000","phone_country_code": "+1","payment_method": "card","payment_method_type": "credit","payment_method_data": {  "card": {    "card_number": "4242424242424242",    "card_exp_month": "12",    "card_exp_year": "2028",    "card_cvc": "123",    "card_holder_name": "Jane Customer"  }},"billing": {  "address": {    "line1": "1600 Amphitheatre Parkway",    "city": "Mountain View",    "state": "CA",    "zip": "94043",    "country": "US",    "first_name": "Jane",    "last_name": "Customer"  },  "phone": {    "number": "6502530000",    "country_code": "+1"  }},"order_details": [  {    "name": "Premium plan",    "quantity": 1,    "amount": 6540,    "currency": "USD"  }],"metadata": {  "order_id": "order_123"}}'

Direct card API payloads can put PCI obligations on your application. If you do not intend to handle raw card data, use the SDK integration guide instead.

Create Payment For Later Confirmation

POST /payments

Use this payload when the payment will be confirmed separately. Only include customer_id when it is an existing Paychtec customer ID returned by the Customers API.

{
  "amount": 6540,
  "currency": "USD",
  "profile_id": "YOUR_PROFILE_ID",
  "customer_id": "cus_acme_42",
  "confirm": false,
  "capture_method": "automatic",
  "description": "Order #123",
  "metadata": {
    "order_id": "order_123"
  }
}

The response includes a payment_id. Use it with POST /payments/:payment_id/confirm.

Confirm Payment

POST /payments/:payment_id/confirm

Use this payload after creating a payment with confirm: false.

{
  "payment_method": "card",
  "payment_method_type": "credit",
  "payment_method_data": {
    "card": {
      "card_number": "4242424242424242",
      "card_exp_month": "12",
      "card_exp_year": "2028",
      "card_cvc": "123",
      "card_holder_name": "Jane Customer"
    }
  },
  "billing": {
    "address": {
      "line1": "1600 Amphitheatre Parkway",
      "city": "Mountain View",
      "state": "CA",
      "zip": "94043",
      "country": "US",
      "first_name": "Jane",
      "last_name": "Customer"
    },
    "phone": {
      "number": "6502530000",
      "country_code": "+1"
    }
  },
  "return_url": "https://example.com/payment-return",
  "browser_info": {
    "ip_address": "203.0.113.42",
    "user_agent": "Mozilla/5.0",
    "accept_header": "text/html",
    "language": "en-US",
    "java_script_enabled": true
  }
}

Capture Payment

POST /payments/:payment_id/capture

Use this for payments created with capture_method: "manual".

{
  "amount_to_capture": 6540,
  "statement_descriptor_prefix": "ACME",
  "statement_descriptor_suffix": "Order123"
}

If you omit amount_to_capture, the API captures the capturable amount when supported by the payment state.

Cancel Payment

POST /payments/:payment_id/cancel

{
  "cancellation_reason": "Customer requested cancellation"
}

Create Refund

POST /refunds

{
  "payment_id": "pay_order_123",
  "refund_id": "refund_order_123_001",
  "amount": 500,
  "reason": "Customer requested refund",
  "refund_type": "Instant",
  "metadata": {
    "order_id": "order_123",
    "support_ticket": "ticket_789"
  }
}

Important fields:

FieldRequiredNotes
payment_idYesPayment to refund.
refund_idNoRecommended for retry-safe reconciliation.
amountNoOmit for full refund; send minor units for partial refund.
reasonNoKeep this human-readable for operations teams.

POST /payment_link

{
  "amount": 5000,
  "currency": "USD",
  "description": "Invoice #1234",
  "link_type": "one_time",
  "expiry": "2024-12-31T23:59:59Z",
  "customer_id": "cus_acme_42",
  "send_email": true,
  "email": "customer@example.com",
  "capture_method": "automatic",
  "authentication_type": "three_ds",
  "require_customer_info": true,
  "payment_link_config": {
    "seller_name": "Acme Inc.",
    "sdk_layout": "tabs",
    "allowed_payment_method_types": ["card", "google_pay"]
  }
}

Create Subscription

POST /subscriptions/create

{
  "customer_id": "cus_acme_42",
  "item_price_id": "standard-plan-USD-Monthly",
  "payment_details": {
    "return_url": "https://example.com/subscription-return",
    "authentication_type": "no_three_ds",
    "capture_method": "automatic",
    "setup_future_usage": "off_session"
  },
  "merchant_reference_id": "sub_order_123",
  "plan_id": "pro_monthly"
}

Subscription create requests also require the X-Profile-Id header. Subscription fields can vary by product configuration; align item_price_id, plan, coupon, billing, and shipping fields with your subscription setup.

Create Payout

POST /payouts/create

{
  "amount": 5000,
  "currency": "USD",
  "customer_id": "cus_acme_42",
  "payout_type": "bank",
  "description": "Vendor payout",
  "metadata": {
    "vendor_id": "vendor_123"
  }
}

Payout availability depends on your account configuration.

Analytics Metrics

POST /analytics/v1/merchant/metrics/payments

{
  "timeRange": {
    "startTime": "2024-01-01T00:00:00Z",
    "endTime": "2024-01-31T23:59:59Z"
  },
  "metrics": ["payment_count", "payment_success_rate", "payment_processed_amount"],
  "source": "BATCH",
  "delta": true,
  "timeSeries": {
    "granularity": "G_ONE_DAY"
  },
  "groupByNames": ["currency"],
  "filters": {
    "currency": ["USD"],
    "status": ["succeeded"]
  }
}

Use the same pattern for refund and dispute analytics with their resource-specific metric paths.

Webhook Payload Shape

Your endpoint receives event payloads for payment, refund, dispute, payout, and subscription changes. Store and process them idempotently.

{
  "merchant_id": "1234567890",
  "event_id": "evt_1234567890",
  "event_type": "payment_succeeded",
  "content": {
    "type": "payment_details",
    "object": {
      "payment_id": "pay_order_123",
      "status": "succeeded",
      "amount": 6540,
      "currency": "USD",
      "metadata": {
        "order_id": "order_123"
      }
    }
  },
  "timestamp": "2024-01-22T10:20:00Z"
}

Webhook payload fields can vary by event type. Verify the signature using the raw request body, process each event_id once, and retrieve the resource from the API if your system needs fields not included in the event. X-Webhook-Signature-512 signs the exact raw request body with HMAC-SHA512. Do not verify against a parsed or reserialized JSON object. For payment events, update local orders using content.object.payment_id or your own content.object.metadata.order_id.

Route Reference

Payments

PurposeMethodPathPayload
Create paymentPOST/paymentsCreate Payment
List paymentsPOST/payments/listFilter body
Retrieve paymentGET/payments/:payment_idNone
Update paymentPOST/payments/:payment_idPayment update fields
Confirm paymentPOST/payments/:payment_id/confirmConfirm Payment
Capture paymentPOST/payments/:payment_id/captureCapture Payment
Cancel paymentPOST/payments/:payment_id/cancelCancel Payment
Approve reviewPOST/payments/:payment_id/approveOptional review fields
Reject reviewPOST/payments/:payment_id/rejectOptional review fields

Customers

PurposeMethodPathPayload
Create customerPOST/customersCreate Customer
List customersGET/customers/listQuery params
Retrieve customerGET/customers/:customer_idNone
Update customerPOST/customers/:customer_idCustomer update fields
Delete customerDELETE/customers/:customer_idNone

Refunds

PurposeMethodPathPayload
Create refundPOST/refundsCreate Refund
List refundsPOST/refunds/listFilter body
Retrieve refundGET/refunds/:refund_idNone
Update refundPOST/refunds/:refund_idRefund update fields
PurposeMethodPathPayload
Create payment linkPOST/payment_linkCreate Payment Link
List payment linksPOST/payment_link/listFilter body
Retrieve payment linkGET/payment_link/:payment_link_idNone

Other Merchant Routes

PurposeMethodPath
List business profilesGET/account/:merchant_id/business_profile
Create API keyPOST/api_keys/:merchant_id
List API keysGET/api_keys/:merchant_id/list
Retrieve API keyGET/api_keys/:merchant_id/:key_id
Update API keyPOST/api_keys/:merchant_id/:key_id
Revoke API keyDELETE/api_keys/:merchant_id/:key_id
List disputesGET/disputes/list
Retrieve disputeGET/disputes/:dispute_id
Accept disputePOST/disputes/accept/:dispute_id
Submit evidencePOST/disputes/evidence
Retrieve evidenceGET/disputes/evidence/:dispute_id
Delete evidenceDELETE/disputes/evidence
Create payoutPOST/payouts/create
List payoutsPOST/payouts/list
Retrieve payoutGET/payouts/:payout_id
Update payoutPUT/payouts/:payout_id
Cancel payoutPOST/payouts/:payout_id/cancel
Fulfill payoutPOST/payouts/:payout_id/fulfill
Create subscriptionPOST/subscriptions/create
Create and confirm subscriptionPOST/subscriptions
Retrieve subscriptionGET/subscriptions/:subscription_id
Update subscriptionPUT/subscriptions/:subscription_id/update
Confirm subscriptionPOST/subscriptions/:subscription_id/confirm
Pause subscriptionPOST/subscriptions/:subscription_id/pause
Resume subscriptionPOST/subscriptions/:subscription_id/resume
Cancel subscriptionPOST/subscriptions/:subscription_id/cancel
Payment metricsPOST/analytics/v1/merchant/metrics/payments
Refund metricsPOST/analytics/v1/merchant/metrics/refunds
Dispute metricsPOST/analytics/v1/merchant/metrics/disputes

Response And Status Handling

Do not fulfill an order just because a create or confirm request returned successfully. Inspect the returned resource status and listen for webhooks.

Common handling:

  • succeeded: fulfill the order.
  • requires_capture: capture later if manual capture was intended.
  • requires_customer_action, requires_redirection, or similar action states: send the customer through the returned next action or redirect flow.
  • processing or pending: wait for a webhook or retrieve the resource later.
  • failed, cancelled, or terminal decline states: show a recoverable failure and allow a new payment attempt.

Webhook Requirements

Your webhook endpoint should:

  • Accept POST requests.
  • Read the raw request body for signature verification.
  • Verify the X-Webhook-Signature-512 header before trusting signed payloads. The signature is an HMAC-SHA512 over the raw request body.
  • Process each event_id once.
  • Update local order, refund, dispute, payout, or subscription state.
  • For payment events, update orders using content.object.payment_id or content.object.metadata.order_id.
  • Retrieve the resource from the API if your system needs fields not included in the event.
  • Return a fast 2xx response after the event is processed or durably queued.

Production Checklist

  • Sandbox payments, refunds, and webhooks have been tested.
  • Idempotency keys are used for retryable mutations.
  • Secret keys are stored only on the server.
  • Raw card data is never logged.
  • Webhook signatures are verified.
  • Duplicate webhook events do not duplicate fulfillment.
  • Payment, refund, dispute, payout, and subscription statuses are stored in your system.
  • Redirect and 3DS return flows are tested.
  • Production API keys and production webhook endpoints are configured.
  • A controlled production transaction has been tested before general launch.