REST API v2 Feature Gaps: Missing endpoints and data needed to migrate from XML-RPC

REST API v2 Feature Gaps: Missing endpoints and data needed to migrate from XML-RPC

We are migrating from the legacy XML-RPC API to REST API v2 and have encountered several critical gaps that require us to maintain dual API implementations. Below are the specific issues we need addressed.


Gap #1: No REST API endpoint to update payment method expiration date

Issue

There is no REST API v2 endpoint to update a payment method’s expiration date. The only available endpoint is DELETE /v2/contacts/{contact_id}/paymentMethods/{payment_method_id} to deactivate a payment method.

Current Workaround (XML-RPC)


$old_sdk->data()->update('CreditCard', $credit_card_id, [

'ExpirationMonth' => $month,

'ExpirationYear' => $year

]);

Request

Add PATCH /v2/contacts/{contact_id}/paymentMethods/{payment_method_id} endpoint with support for updating:

  • expiration_month

  • expiration_year


Gap #2: No REST API endpoint to query Invoice table by contact

Issue

Cannot retrieve all invoices for a contact via REST API v2. This is essential for displaying billing history to customers.

Note: OrdersApi::listOrderPayments(order_id) exists but:

  • Requires an order_id, not contact_id

  • Returns InvoiceOrderPayment objects (payment records only)

  • Does NOT provide full invoice data (TotalDue, TotalPaid, InvoiceType, etc.)

  • Cannot list all invoices for a contact in one call

Current Workaround (XML-RPC)


$old_sdk->data()->findByField("Invoice", 1000, 0, "ContactId", $contact_id, [

'Id',

'TotalDue',

'TotalPaid',

'RefundStatus',

'PayStatus',

'InvoiceType',

'InvoiceTotal',

'DateCreated',

'CreditStatus'

]);

Request

Add GET /v2/contacts/{contact_id}/invoices endpoint that returns invoice data including:

  • Invoice ID

  • Total due/paid amounts

  • Payment status

  • Invoice type

  • Creation date

  • Refund/credit status


Gap #3: No REST API endpoint to query Payment table

Issue

Cannot query the Payment table to retrieve payment history details such as payment date, amount, type, and associated invoice.

Current Workaround (XML-RPC)


$old_sdk->data()->query("Payment", $limit, $page,

['ContactId' => $contact_id, 'PayAmt' => $amount],

['Id', 'ContactId', 'InvoiceId', 'PayDate', 'PayAmt', 'PayNote', 'PayType'],

'PayDate',

false // descending

);

Request

Add GET /v2/contacts/{contact_id}/payments endpoint that returns payment data including:

  • Payment ID

  • Invoice ID

  • Payment date

  • Payment amount

  • Payment type

  • Payment notes


Gap #4: CreditCard table ID ≠ REST payment_method_id (no mapping provided)

Issue

The XML-RPC CreditCard.Id and REST API payment_method_id are completely different ID systems with no mapping provided. This makes it impossible to correlate data between the two APIs.

For example:

  • XML-RPC CreditCard IDs: 135076, 142485

  • REST payment_method_ids: 3289, 20498, 30157

These IDs have no relationship to each other.

Current Workaround

  1. Query CreditCard table via XML-RPC to get the Last4 digits

  2. Query REST payment methods to get all cards

  3. Match by Last4 to find the corresponding REST payment_method_id

This workaround is unreliable if a contact has multiple cards with the same last 4 digits.

Request

Either:

  1. Add a legacy_credit_card_id field to the REST payment method response, OR

  2. Provide a mapping endpoint: GET /v2/paymentMethods/legacy/{credit_card_id}, OR

  3. Include the legacy CreditCard ID in the REST payment method model


Gap #5: No REST API endpoint to update Order (Job) custom fields

Issue

Cannot update custom fields on orders via REST API v2.

Note: OrdersApi::updateOrder(order_id) exists but UpdateOrderRequest model does NOT include custom fields support. Only these fields are available:

  • contact_id, lead_affiliate_id, notes, order_time, order_title, order_type

  • payment_plan, promo_codes, sales_affiliate_id, shipping_address, terms

Current Workaround (XML-RPC)


$old_sdk->data()->update("Job", $order_id, [

$custom_field_name => $value

]);

Request

Add custom fields support to UpdateOrderRequest model for PATCH /v2/orders/{order_id}, similar to how contacts support custom fields.


Summary

| Gap | Missing Functionality | Current Workaround |

|-----|----------------------|-------------------|

| #1 | Update payment method expiration | XML-RPC CreditCard.update() |

| #2 | Query invoices | XML-RPC Invoice.findByField() |

| #3 | Query payments | XML-RPC Payment.query() |

| #4 | CreditCard ID to payment_method_id mapping | Match by Last4 (unreliable) |

| #5 | Update order custom fields | XML-RPC Job.update() |

These gaps force us to maintain both XML-RPC and REST API v2 implementations, which:

  • Increases code complexity and maintenance burden

  • Requires two sets of authentication tokens

  • Slows down operations due to multiple API calls

  • Creates potential data consistency issues

We would greatly appreciate these gaps being addressed to enable a complete migration to REST API v2.

Thank you!

1 Like

Hi @Mark_Ginat,

Thanks so much for the detailed feedback and for clearly outlining these gaps. I really appreciate you taking the time to provide all the specifics; it makes it much easier for us to understand the issues and discuss potential solutions.

Gap #1: No REST API endpoint to update payment method expiration date

In v2, there is no direct endpoint to edit an existing payment method. Card data is managed by the payment processors (e.g., Stripe, Rainforest). The supported approach is to delete the old payment method and create a new one with the updated expiration.

For guidance on how payment methods are handled in v2, please see the documentation:
Keap Payments API Integration Configuration

This approach is intentional and reflects the way v2 is designed: cards are no longer treated as entities owned by our system, and updates like expiration changes are handled through the payment processors’ components.

Gap #2: No REST API endpoint to query Invoice table by contact

In v2, orders and invoices are handled in a more unified way, so an order essentially represents its invoice. You can use the GET /v2/orders endpoint and filter by contact_id. Can you confirm if this meets your need?

Gap #3: No REST API endpoint to query Payment table

Thanks for reporting this, I will bring it up internally.

Gap #4: CreditCard table ID ≠ REST payment_method_id (no mapping provided)

  1. You actually reported this one here, and I’ve already flagged it internally.

Gap #5: No REST API endpoint to update Order (Job) custom fields

  1. I will report it, thanks for bringing it up.

Hi @OmarAlmonte ,

Gap #2 - Update: Confirmed Working

Thank you for the guidance on Gap #2! We’ve confirmed that refund data IS available in the v2 API.

Solution:

  1. GET /v2/orders?filter=contact_id=={id} - Gets orders for a contact

  2. GET /v2/orders/{id}/payments - Gets payment transactions (includes refunds)

Refund transactions appear with status: "REFUNDED" and negative amounts. For SDK users, OrdersApi->listOrderPayments(order_id) works perfectly.

Minor note: The refund_total field shown in the schema isn’t included in the actual response, but individual refund transactions in the payments endpoint provide everything needed.

Gap #2 is now fully resolved for our use case. Thanks for your help!

Gap #3: No REST API endpoint to query Payment table

Status: :white_check_mark: RESOLVED - Same solution as Gap #2

Issue

Cannot query the Payment table to retrieve payment history details such as payment date, amount, type, and associated invoice.

Solution (v2 SDK)

Use the same approach as Gap #2 - listOrderPayments() provides all payment transaction data:

// Get orders for contact
$orders = $keap->orders()->listOrders(filter: "contact_id==$contact_id");

// Get payment transactions for each order
foreach ($orders as $order) {
    $payments = $keap->orders()->listOrderPayments(order_id: $order->getId());
    
    // Each payment object includes:
    // - getId() - Payment ID
    // - getInvoiceId() - Invoice ID  
    // - getPayTime() - Payment date
    // - getAmount() - Payment amount
    // - getPayStatus() - Payment status (APPROVED, REFUNDED, etc.)
    // - getNote() - Payment notes
    // - getRefundInvoicePaymentId() - For tracking refunds
}

This provides complete payment history data without needing XML-RPC.

Original Request (No Longer Needed)

Add GET /v2/contacts/{contact_id}/payments endpoint - Resolved via listOrderPayments()