Partner API Reference

Complete endpoint reference for partner integrations

Quick-reference for all partner-accessible endpoints. For flow diagrams, webhook verification examples, and PCI scope notes see PARTNER_GUIDE.md.


Base URL and Authentication

Base URL:  https://api.foundrypay.io
Auth:      Authorization: ApiKey <your-api-key>
Content:   Content-Type: application/json

Every request is automatically scoped to your merchant account. API keys are generated in the portal under Settings → API Keys.


Payment Requests

Create a Payment Request

POST /v1/payment-requests

Request body

Field Type Required Description
referenceId string Yes Your order/invoice number. Returned in all webhooks.
buyerEmail string Yes Buyer email. Enables saved-card recall for returning buyers.
amount number Yes Amount in dollars (e.g. 312.50). Range: 0.01 – 1,000,000.
currency string No ISO 4217. Default: "USD".
captureMode string No "manual" (default) or "immediate".
acceptedPaymentMethod string No "card", "ach", or omit to let buyer choose.
buyerCompany string No Company name shown in the portal.
returnUrl string No Redirect after payment on mobile.
billingAddress object No See Billing Address.
lineItems array No See Line Items. Amounts in cents.

Response 201

{
  "id":        "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "token":     "abc123xyz...",
  "iframeUrl": "https://pay.foundrypay.io/enter/abc123xyz...",
  "status":    "Pending",
  "expiresAt": "2024-06-01T13:00:00Z"
}

Expires after 60 minutes.


Get Payment Request Status

GET /v1/payment-requests/{token}

Pass the string token (not the UUID) returned from the create call.

Response 200

{
  "id":                    "3fa85f64-...",
  "referenceId":           "ORD-20240601-001",
  "buyerEmail":            "buyer@example.com",
  "buyerCompany":          "Acme Wholesale",
  "amount":                312.50,
  "currency":              "USD",
  "status":                "Collected",
  "createdAt":             "2024-06-01T12:00:00Z",
  "expiresAt":             "2024-06-01T13:00:00Z",
  "completedAt":           "2024-06-01T12:34:56Z",
  "acceptedPaymentMethod": "card"
}
Status Meaning
Pending Waiting for buyer to complete payment.
Collected Card entered. Ready to authorize.
Expired 60-minute window elapsed.
Cancelled Cancelled by the platform.

Request Card Refresh

When a stored card has expired or been declined during authorization, send the buyer a link to enter a replacement card.

POST /v1/payment-requests/{id}/card-update

The {id} is the UUID of the source payment request (status must be Collected).

Request body

Field Type Required Description
returnUrl string No Mobile redirect after card entry.

Response 201

{
  "id":        "9b1b3a2e-...",
  "token":     "xyz789...",
  "iframeUrl": "https://pay.foundrypay.io/enter/xyz789...",
  "expiresAt": "2024-06-01T14:00:00Z"
}

Show or send the iframeUrl to the buyer. On completion:

Expires after 60 minutes.


Card Enrollment

Store a card on file without tying it to any specific order or invoice.

POST /v1/card-enrollments

Request body

Field Type Required Description
buyerEmail string Yes Buyer email. Used as the Adyen shopper identifier.
buyerReference string No Your own buyer/account ID. Returned in the card.enrolled webhook.
buyerCompany string No Company name (display only).
returnUrl string No Mobile redirect after card entry.
billingAddress object No Pre-populated in the form. See Billing Address.

Response 201

{
  "id":        "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "token":     "abc123xyz...",
  "iframeUrl": "https://pay.foundrypay.io/enter/abc123xyz...",
  "expiresAt": "2024-06-01T13:00:00Z"
}

Show the iframeUrl to the buyer. On completion you receive a card.enrolled webhook with the paymentMethodId. Use that ID in future POST /v1/payments calls.

Expires after 60 minutes.


Payments

Authorize

Authorize and capture the funds for a Collected payment request.

POST /v1/payments

Request body

Field Type Required Description
paymentRequestId UUID Yes ID of the Collected payment request.

Response 200

{
  "id":            "7c4a9e1d-...",
  "status":        "Authorized",
  "pspReference":  "853612...",
  "amount":        312.50,
  "currency":      "USD",
  "referenceId":   "ORD-20240601-001",
  "authorizedAt":  "2024-06-01T12:35:00Z"
}
Payment Status Meaning
Authorized Funds held. Capture via portal to settle.
Captured Funds settled (immediate-capture mode or manual capture).
Failed Authorization declined.
Voided Authorization cancelled before capture.
Refunded Post-capture refund issued.

Batch Authorize

Authorize multiple payment requests in one call. Always returns HTTP 200; inspect each item's success field — the batch status code does not indicate per-item success.

POST /v1/payments/batch-authorize

Request body

{
  "items": [
    { "referenceId": "ORD-001" },
    { "referenceId": "ORD-002", "amount": 150.00 }
  ]
}
Field Type Required Description
items[].referenceId string Yes Your order/invoice reference.
items[].amount number No Override the payment request amount (advanced use).

Response 200

{
  "results": [
    { "referenceId": "ORD-001", "success": true,  "paymentId": "7c4a9e1d-..." },
    { "referenceId": "ORD-002", "success": false, "error": "No collected payment request found" }
  ],
  "summary": { "total": 2, "succeeded": 1, "failed": 1 }
}

Transactions

List Transactions

GET /v1/transactions

Query parameters

Parameter Type Description
status string Filter by payment status (e.g. Authorized, Captured).
search string Full-text search on reference ID or buyer email.
paymentRequestId UUID Return only transactions for a specific payment request.
from ISO 8601 Earliest transaction date.
to ISO 8601 Latest transaction date.
page integer Page number (1-based).
pageSize integer Results per page (default 20).

Response 200 — paginated list of payment objects.


Shared Object Schemas

Billing Address

{
  "street":          "123 Main St",
  "houseNumberOrName": "Suite 400",
  "city":            "Chicago",
  "stateOrProvince": "IL",
  "postalCode":      "60601",
  "country":         "US"
}

All fields optional; any provided are forwarded to the card network for AVS.

Line Items

Array of objects for Level 3 interchange qualification. Amounts in cents.

[
  {
    "id":                   "SKU-001",
    "description":          "Widget A",
    "quantity":             2,
    "amountExcludingTax":   25000,
    "amountIncludingTax":   25000,
    "taxAmount":            0,
    "taxPercentage":        0
  }
]

Webhooks

Envelope

All webhooks share a common envelope:

{
  "eventType": "payment_request.completed",
  "createdAt": "2024-06-01T12:34:56Z",
  "data":      { }
}

Event Payloads

payment_request.completed

{
  "referenceId":     "ORD-20240601-001",
  "status":          "collected",
  "paymentMethodId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}

card.enrolled

{
  "buyerReference":  "BUYER-4521",
  "buyerEmail":      "buyer@example.com",
  "paymentMethodId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "last4":           "1111",
  "brand":           "visa"
}

card.updated

{
  "referenceId":     "ORD-20240601-001",
  "paymentMethodId": "7c4a9e1d-...",
  "last4":           "4242",
  "brand":           "mastercard"
}

payment_request.expired

{
  "referenceId": "ORD-20240601-001"
}

Signature Verification

Every webhook includes X-Foundry-Signature: sha256=<hex-digest>.

import hmac, hashlib

def verify(secret: str, body: bytes, header: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, header)
bool Verify(string secret, byte[] body, string header)
{
    using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
    var digest = "sha256=" + Convert.ToHexString(hmac.ComputeHash(body)).ToLower();
    return CryptographicOperations.FixedTimeEquals(
        Encoding.UTF8.GetBytes(digest),
        Encoding.UTF8.GetBytes(header));
}

Respond with any 2xx to acknowledge. Failed deliveries are retried 3 times with exponential backoff.


Error Responses

{ "error": "Payment request not found or not in collected state" }
HTTP Status Meaning
400 Missing required field or invalid value.
401 Invalid or missing API key.
404 Resource not found.
409 Conflict — e.g. payment request already collected or expired.
422 Payment could not be processed (e.g. declined).
502 Upstream error from payment network. Retry after a short delay.

Test Cards

Scenario Card Number Expiry CVV
Visa — success 4111 1111 1111 1111 Any future Any 3 digits
Mastercard — success 5500 0000 0000 0004 Any future Any 3 digits
Declined 4000 0000 0000 0002 Any future Any 3 digits
Insufficient funds 4000 0000 0000 9995 Any future Any 3 digits

ACH testing: routing 021000021, any 10-digit account number.