mutation createPaymentPlanSessionAuthenticated

Creates a payment plan session used by the checkout process to create and authorize a payment plan.

Returns PaymentPlanSession!

Arguments

ArgumentTypeDescription
inputCreatePaymentPlanSessionInput!

Example request

curl -X POST 'https://graph.clientloop.com/' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <api-key>' \
  -d '{
    "query": "mutation CreatePaymentPlanSession($input: CreatePaymentPlanSessionInput!) { createPaymentPlanSession(input: $input) { id orgId contactId contact { id orgId ownerId name givenName familyName email phone deletedAt createdAt updatedAt idv { status createdAt completedAt selfieVideoUrl nameMatch dateOfBirthMatch phoneNumberMatch addressMatch taxIdMatch livenessCheck facialComparisonCheck } paymentMethods { __typename } } amount currency status frequency startDate occurrences callbackUrl cancelUrl successUrl link expirationDate paymentPlanId createdAt updatedAt checkoutConfigurationId brandLogoUrl brandName } }",
    "variables": {
      "input": {
        "orgId": "abc123",
        "contactId": "abc123",
        "amount": "100.00",
        "currency": "USD",
        "frequency": "Weekly",
        "startDate": "2025-01-01",
        "occurrences": 42
      }
    }
  }'
const response = await fetch('https://graph.clientloop.com/', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer <api-key>',
  },
  body: JSON.stringify({
    query: `
      mutation CreatePaymentPlanSession($input: CreatePaymentPlanSessionInput!) {
        createPaymentPlanSession(input: $input) {
          id
          orgId
          contactId
          contact {
            id
            orgId
            ownerId
            name
            givenName
            familyName
            email
            phone
            deletedAt
            createdAt
            updatedAt
            idv {
              status
              createdAt
              completedAt
              selfieVideoUrl
              nameMatch
              dateOfBirthMatch
              phoneNumberMatch
              addressMatch
              taxIdMatch
              livenessCheck
              facialComparisonCheck
            }
            paymentMethods {
              __typename
            }
          }
          amount
          currency
          status
          frequency
          startDate
          occurrences
          callbackUrl
          cancelUrl
          successUrl
          link
          expirationDate
          paymentPlanId
          createdAt
          updatedAt
          checkoutConfigurationId
          brandLogoUrl
          brandName
        }
      }
    `,
    variables: {
      "input": {
        "orgId": "abc123",
        "contactId": "abc123",
        "amount": "100.00",
        "currency": "USD",
        "frequency": "Weekly",
        "startDate": "2025-01-01",
        "occurrences": 42
      }
    },
  }),
});

const { data, errors } = await response.json();
<?php

$body = <<<'JSON'
{
  "query": "mutation CreatePaymentPlanSession($input: CreatePaymentPlanSessionInput!) { createPaymentPlanSession(input: $input) { id orgId contactId contact { id orgId ownerId name givenName familyName email phone deletedAt createdAt updatedAt idv { status createdAt completedAt selfieVideoUrl nameMatch dateOfBirthMatch phoneNumberMatch addressMatch taxIdMatch livenessCheck facialComparisonCheck } paymentMethods { __typename } } amount currency status frequency startDate occurrences callbackUrl cancelUrl successUrl link expirationDate paymentPlanId createdAt updatedAt checkoutConfigurationId brandLogoUrl brandName } }",
  "variables": {
    "input": {
      "orgId": "abc123",
      "contactId": "abc123",
      "amount": "100.00",
      "currency": "USD",
      "frequency": "Weekly",
      "startDate": "2025-01-01",
      "occurrences": 42
    }
  }
}
JSON;

$ch = curl_init('https://graph.clientloop.com/');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_HTTPHEADER => [
    'Content-Type: application/json',
    'Authorization: Bearer <api-key>',
  ],
  CURLOPT_POSTFIELDS => $body,
]);

$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

var body = """
{
  "query": "mutation CreatePaymentPlanSession($input: CreatePaymentPlanSessionInput!) { createPaymentPlanSession(input: $input) { id orgId contactId contact { id orgId ownerId name givenName familyName email phone deletedAt createdAt updatedAt idv { status createdAt completedAt selfieVideoUrl nameMatch dateOfBirthMatch phoneNumberMatch addressMatch taxIdMatch livenessCheck facialComparisonCheck } paymentMethods { __typename } } amount currency status frequency startDate occurrences callbackUrl cancelUrl successUrl link expirationDate paymentPlanId createdAt updatedAt checkoutConfigurationId brandLogoUrl brandName } }",
  "variables": {
    "input": {
      "orgId": "abc123",
      "contactId": "abc123",
      "amount": "100.00",
      "currency": "USD",
      "frequency": "Weekly",
      "startDate": "2025-01-01",
      "occurrences": 42
    }
  }
}
""";

var request = HttpRequest.newBuilder(URI.create("https://graph.clientloop.com/"))
    .header("Content-Type", "application/json")
    .header("Authorization", "Bearer <api-key>")
    .POST(HttpRequest.BodyPublishers.ofString(body))
    .build();

var response = HttpClient.newHttpClient()
    .send(request, HttpResponse.BodyHandlers.ofString());

System.out.println(response.body());
using System.Net.Http;
using System.Text;

var body = """
{
  "query": "mutation CreatePaymentPlanSession($input: CreatePaymentPlanSessionInput!) { createPaymentPlanSession(input: $input) { id orgId contactId contact { id orgId ownerId name givenName familyName email phone deletedAt createdAt updatedAt idv { status createdAt completedAt selfieVideoUrl nameMatch dateOfBirthMatch phoneNumberMatch addressMatch taxIdMatch livenessCheck facialComparisonCheck } paymentMethods { __typename } } amount currency status frequency startDate occurrences callbackUrl cancelUrl successUrl link expirationDate paymentPlanId createdAt updatedAt checkoutConfigurationId brandLogoUrl brandName } }",
  "variables": {
    "input": {
      "orgId": "abc123",
      "contactId": "abc123",
      "amount": "100.00",
      "currency": "USD",
      "frequency": "Weekly",
      "startDate": "2025-01-01",
      "occurrences": 42
    }
  }
}
""";

using var client = new HttpClient();
using var content = new StringContent(body, Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Add("Authorization", "Bearer <api-key>");

var response = await client.PostAsync("https://graph.clientloop.com/", content);
var result = await response.Content.ReadAsStringAsync();

Types

input CreatePaymentPlanSessionInput

FieldTypeDescription
orgIdID!

ID of the organization this payment session belongs to

contactIdID!

ID of the platform contact associated with this payment plan session

amountAmount!

Payment amount to be charged on the configured frequency.

currencyCurrency!

Currency of the payment

frequencyPaymentPlanFrequency!

Frequency of the payment plan

startDateDate!

Start date of the payment plan

occurrencesInt!

Number of payment occurrences to be run on the configured frequency from the start date

callbackUrlURL

URL to receive payment session events

cancelUrlURL

URL to redirect after a payment session is canceled by the customer

successUrlURL

URL to redirect after a payment session is completed by the customer

expirationDateDateTime

Optional expiration date for the payment session. ISO 8601 format.

createPendingPaymentPlanBoolean

Optionally create a pending payment plan record for this payment plan session. Default is false which means a payment plan record is created upon payment plan session completion. Set this to true if you require a pending payment plan to be visible in the payment plan list in the dashboard. This is useful for use cases involving payment plan sessions without expirations. This setting may only be set on payment plan session creation.

checkoutConfigurationIdID

The checkout configuration ID to be used for this payment plan session. If a checkout configuration ID is not provided, the default checkout configuration will be used.

brandLogoUrlURL

Optional URL to a logo image to display during checkout, overriding the default branding. The caller supplies a URL that is used to render the logo.

brandNameString

Optional brand or merchant name to display during checkout, overriding the organization name.

type PaymentPlanSession

FieldTypeDescription
idID!

Unique identifier for this payment plan session

orgIdID!

ID of the organization this payment session belongs to

contactIdID!

ID of the platform contact associated with this payment plan session

contactContact

Platform contact associated with this payment plan session

amountAmount!

Payment amount to be charged on the configured frequency.

currencyCurrency!

Currency of the payment

statusPaymentPlanSessionStatus!

Status of the payment plan session

frequencyPaymentPlanFrequency!

Frequency of the payment plan

startDateDate!

Start date of the payment plan

occurrencesInt!

Number of payment occurrences to be run on the configured frequency from the start date

callbackUrlURL

URL to receive payment session events

cancelUrlURL

URL to redirect after a payment session is canceled by the customer

successUrlURL

URL to redirect after a payment session is completed by the customer

linkURL

Link to the payment plan session. This will be null if the session is expired or completed. This link is used to redirect the user to the payment page or may be used to embedded payment flow depending on the configuration provided.

expirationDateDateTime

Optional expiration date for the payment session. ISO 8601 format.

paymentPlanIdID

ID of the payment plan created by this payment plan session

createdAtDateTime!

Date the payment session was created

updatedAtDateTime!

Date the payment session was last updated

checkoutConfigurationIdID

The checkout configuration ID used for this payment session.

brandLogoUrlURL

Optional caller-supplied URL to a logo image to display during checkout, overriding the default branding.

brandNameString

Optional caller-supplied brand or merchant name to display during checkout, overriding the organization name.

scalar Amount

A monetary amount with up to two decimal places. Ex. 111.11

scalar Currency

Three letter ISO 4217 currency code. Ex. USD

enum PaymentPlanFrequency

  • Weekly
  • Monthly
  • Quarterly
  • Yearly

scalar Date

ISO 8601 formatted date in the format YYYY-MM-DD

scalar URL

A URL with protocol and port. ex. https://example.com

scalar DateTime

ISO 8601 formatted date time. Ex. 2023-11-23T14:30:00Z

type Contact

FieldTypeDescription
idID!

Unique ID of the contact.

orgIdID!

ID of the organization that owns the contact.

ownerIdID!

Global ID of the owning organization (Org#<id>). Deprecated; use orgId.

Deprecated: Use `orgId` instead.
nameString!

Full name of the contact.

givenNameString

Given name of the contact.

familyNameString

Family name of the contact.

emailEmail

Email address of the contact.

phonePhone

Phone number of the contact. This will be validated and normalized to the E.164 format.

deletedAtString

Set when the contact has been soft-deleted; null for an active contact.

createdAtString!

Date and time when the contact was created.

updatedAtString!

Date and time when the contact was last updated.

idvContactIdvSessionDetail

The latest Plaid identity-verification session for this contact. On the public graph this exposes the session timestamps, the captured selfie video, the captured identity documents, and the individual check outcomes; the remaining detail is private-graph only. Null when the contact has never started a session. Fetched on demand from Plaid — request it only when needed.

paymentMethods(input)PaymentMethodConnection!

Payment methods stored against this contact, as a Relay-style, cursor-paginated connection, newest first.

Page forward by starting with first: N, then passing the previous response's pageInfo.endCursor back as after (repeat while pageInfo.hasNextPage); page backward with last + before. Deleted methods are omitted unless includeDeleted is set.

enum PaymentPlanSessionStatus

  • Expired
  • Active
  • Completed
  • Canceled

scalar Email

An email address

scalar Phone

E.164 formatted phone number. Ex. +14155554345

type ContactIdvSessionDetail

Details of a contact's Plaid identity-verification session, fetched on demand from Plaid. The public graph exposes the timestamps, the captured selfie video, the captured identity documents, and the individual check outcomes; the remaining fields — including the raw Plaid pass-throughs they are derived from — are private-graph only.

FieldTypeDescription
statusContactIdvSessionStatus!

Where the verification as a whole stands. Success, Failed and PendingReview are all terminal and all carry captured identity; Active is still in progress, and Expired or Canceled never produced one.

createdAtDateTime!
completedAtDateTime
documents[ContactIdvDocument!]!

Captured identity documents, pulled out of documentary_verification: each document's category and its captured images.

selfieVideoUrlString

URL of the captured selfie video, pulled out of selfieCheck for direct access. Plaid-hosted and expiring; null when the template did not capture a selfie video.

nameMatchIdvMatchSummary

How the name that the contact supplied compared against Plaid's data sources. Null when the KYC step has not run.

dateOfBirthMatchIdvMatchSummary

How the date of birth compared against Plaid's data sources. Null when the KYC step has not run.

phoneNumberMatchIdvMatchSummary

How the phone number compared against Plaid's data sources. Null when the KYC step has not run.

addressMatchIdvMatchSummary

How the address compared against Plaid's data sources. Null when the KYC step has not run.

taxIdMatchIdvMatchSummary

How the tax id (SSN) compared against Plaid's data sources, from Plaid's id_number check. Null when the KYC step has not run.

livenessCheckIdvLivenessStatus

Whether the captured selfie passed liveness detection. Null when the selfie step has not run or captured no analysis.

facialComparisonCheckIdvFacialComparisonStatus

Whether the captured selfie matched the face on the identity document. Null when the selfie step has not run or captured no analysis.

type PaymentMethodConnection

A page of payment methods following the Relay Connection spec. edges holds the payment methods in this page (each with its cursor) and pageInfo describes whether more pages exist in each direction plus the cursors that bound this page.

FieldTypeDescription
edges[PaymentMethodEdge!]!

The payment methods in this page, ordered newest first.

pageInfoPageInfo!

Pagination metadata for this page: hasNextPage/hasPreviousPage and the startCursor/endCursor bounds.

input PaymentMethodsInput

Filter and pagination for a payment methods connection.

Pagination is Relay cursor-based, not page/offset based — see the Relay Connections spec. Page forward with first + after, or backward with last + before; never mix the two directions in a single call. Cursors are opaque strings taken from a previous response's pageInfo (or edges[].cursor) — treat them as black boxes, don't build or parse them yourself.

FieldTypeDescription
firstInt

Forward pagination: return at most the first N payment methods from the start of the result window. Pair with after to walk forward. Do not combine with last/before. When omitted (and no last), a default page size is used.

afterString

Forward pagination cursor: return the payment methods that come after this cursor. Use the pageInfo.endCursor from the previous page. Pair with first.

lastInt

Backward pagination: return at most the last N payment methods nearest the end of the result window. Pair with before to walk backward. Do not combine with first/after.

beforeString

Backward pagination cursor: return the payment methods that come before this cursor. Use the pageInfo.startCursor from the previous page. Pair with last.

typePaymentMethodType

Return only methods of this kind. Omit to return both cards and bank accounts.

statusPaymentMethodStatus

Return only methods in this state. Omit to return every state.

includeDeletedBoolean

Include methods that have been deleted. Defaults to false, so deleted methods are omitted. Deleted methods can never be charged; include them only to render history.

enum ContactIdvSessionStatus

Where a contact's verification stands. Mirrors the shared IdvSessionStatus but is declared separately so the contact graph's public surface does not depend on a type owned by the application module.

  • Active
  • Expired
  • Canceled
  • Success
  • Failed
  • PendingReview

type ContactIdvDocument

A captured identity document from a contact's Plaid documentary verification.

FieldTypeDescription
categoryString

Document category as classified by Plaid (e.g. drivers_license, id_card, passport). Null when Plaid could not classify the document.

images[ContactIdvDocumentImage!]!

Captured images for this document (e.g. originalFront, croppedBack, face).

enum IdvMatchSummary

How one value that the contact supplied compared against the data sources that Plaid checked it against. NoData means Plaid held nothing to compare with; NoInput means the contact supplied nothing to compare.

  • Match
  • PartialMatch
  • NoMatch
  • NoData
  • NoInput

enum IdvLivenessStatus

Whether the captured selfie passed liveness detection — that a live person was present rather than a photograph or a screen.

  • Success
  • Failed

enum IdvFacialComparisonStatus

How the captured selfie compared against the face on the captured identity document. NoInput means one of the two was never captured.

  • Match
  • NoMatch
  • NoInput

type PaymentMethodEdge

A single element of a PaymentMethodConnection page: the payment method itself (node) plus the opaque cursor that points at it. Pass a cursor back as after (forward) or before (backward) to page relative to this row.

FieldTypeDescription
nodePaymentMethod!

The payment method at this position in the page.

cursorString!

Opaque cursor identifying this payment method's position, for use as after or before.

type PageInfo

PageInfo type for cursor-based pagination following the Relay specification for cursor based pagination.

FieldTypeDescription
hasNextPageBoolean!
hasPreviousPageBoolean!
startCursorString
endCursorString

enum PaymentMethodType

The kind of instrument a stored payment method holds.

  • CardA credit or debit card.
  • BankAccountA bank account debited over ACH.

enum PaymentMethodStatus

Whether a stored payment method can still be charged.

  • ActiveUsable for new payments.
  • ExpiredPast its expiration date. Charges will be declined until the customer stores a new method.
  • InvalidThe provider no longer accepts the stored credential, for example because the card was reported lost or the bank account was closed.

type ContactIdvDocumentImage

A single captured image belonging to a ContactIdvDocument. Plaid-hosted and expiring.

FieldTypeDescription
nameString

Image identifier (e.g. originalFront, croppedBack, face).

urlString

Plaid-hosted URL of the image. Expires.

type PaymentMethod

A payment instrument stored against a contact so it can be charged again without the customer re-entering it.

A payment method is created by completing a payment session whose storePaymentMethod was not Disabled, and charged afterwards with chargePaymentMethod. Payment options that are unsuitable for storing are not offered during such a session — consumer financing such as FlexPay, for example, applies to a single purchase and cannot act as a method on file.

FieldTypeDescription
idID!

Globally unique id of the payment method, a KSUID behind the pmd category prefix. Treat it as opaque: the prefix exists so the server can route the id to this type, and its format is not part of the contract. Refetchable through the Relay node(id:) query as well as paymentMethod(id:).

orgIdID!

Organization that owns this payment method.

contactIdID!

ID of the contact this payment method is stored against.

contactContact

Contact this payment method is stored against.

typePaymentMethodType!

Whether this method is a card or a bank account. Determines which of card and bankAccount is populated.

statusPaymentMethodStatus!

Whether the method can still be charged.

providerPaymentProvider!

Payment provider holding the underlying credential.

configurationIdID

ID of the provider configuration the credential is stored under. Charges against this method run through the same configuration.

cardPaymentMethodCard

Card detail. Populated when type is Card, otherwise null.

bankAccountPaymentMethodBankAccount

Bank account detail. Populated when type is BankAccount, otherwise null.

supportedRecurringProcessingModels[RecurringProcessingModel!]!

The ways this method may be used for a later payment. A method is stored under the model declared on its payment session, and the provider reports which models the resulting credential supports. Read it before offering a customer a subscription against a method that may not carry one.

billingAddressGlobalAddress

Billing address captured alongside the instrument.

paymentSessionIdID

ID of the payment session that stored this payment method.

deletedAtDateTime

Set when the payment method has been deleted; null while it is usable. A deleted method is excluded from Contact.paymentMethods unless includeDeleted is set, and can no longer be charged.

createdAtDateTime!

Date the payment method was stored.

updatedAtDateTime!

Date the payment method was last updated.

enum PaymentProvider

  • NMI
  • Plaid
  • CLP

type PaymentMethodCard

Card detail for a stored payment method whose type is Card.

FieldTypeDescription
brandString

Card brand as reported by the provider. Ex. Visa

last4String!

Last four digits of the card number.

expirationMonthInt!

Expiration month, 1-12.

expirationYearInt!

Expiration year, four digits. Ex. 2029

cardholderNameString

Name on the card as captured when the method was stored.

fundingPaymentMethodCardFunding!

Whether the card draws on a credit, debit or prepaid account. Surcharging rules turn on this distinction. It can only be captured from the provider's response at the moment the method is stored, never looked up afterwards, and some providers report it only when the merchant's account is configured to include it, so a method stored without it stays Unknown for life.

type PaymentMethodBankAccount

Bank account detail for a stored payment method whose type is BankAccount.

FieldTypeDescription
institutionNameString

Name of the institution holding the account. Ex. Chase. Depends on the provider: reported for accounts linked through Plaid, and generally absent for accounts stored directly with the card processor, which does not return it.

accountHolderNameString

Name on the account as reported by the provider.

last4String

Last four digits of the account number.

accountTypePaymentMethodBankAccountType

Whether the account is a checking or savings account.

enum RecurringProcessingModel

How a stored payment method may be used for a later payment, following the card networks' stored-credential framework. The model is declared when a method is stored and again on every payment made from it, and it decides how that later payment is treated for Strong Customer Authentication: a Subscription or UnscheduledCardOnFile charge is one you initiate and falls outside SCA, while a CardOnFile charge does not.

What separates the two models you initiate is the schedule, not the amount. A run of payments on a fixed interval is a Subscription even when the amount differs every time.

  • CardOnFileDetails kept so a returning customer checks out faster, where the later payment is one the customer starts themselves — a "pay with my saved card" button in your own checkout, for example.
  • SubscriptionYou initiate the payment, and the payments follow a fixed schedule the customer agreed to in advance. The amount may be fixed or may vary from one charge to the next: a monthly invoice whose total changes every month is still a subscription, because it is the interval that is fixed.
  • UnscheduledCardOnFileYou initiate the payment, and the payments follow no fixed schedule. For example a top-up triggered by a balance falling below a threshold, or an invoice raised whenever a job is finished.

type GlobalAddress

Address of a physical location

FieldTypeDescription
lines[String!]!

Street, unit, building number, etc.

localityString

City, town or municipality designation

administrativeAreaString

State, province or area designation

postalCodeString

Postal code or ZIP code

countryCodeString!

2-letter country code. Ex. USA

enum PaymentMethodCardFunding

How a stored card funds a payment, when the provider reports it.

  • Credit
  • Debit
  • Prepaid
  • Unknown

enum PaymentMethodBankAccountType

The kind of bank account a stored payment method debits.

  • Checking
  • Savings