[Stripe] How to develop nodes / APIs with complex nested data structures?

Describe the issue/error/question

We work on extending the Stripe Node with more functionality in regards of their newer APIs. In particular the PaymentIntent API. This API is quite nasty as it gets very complex in terms of the possible input in the request objects. The request data is also highly variable based on certain inputs.

To be more precise: There are payment_method_options for each and every payment_method. Each option can be a multi dimensional object.

You can see what I mean here: Stripe API reference – The PaymentIntent object – curl
Just expand some of the child attributes levels.
Or take a look at their Typings … stripe-node/PaymentIntents.d.ts at master · stripe/stripe-node · GitHub :scream:

We considered implementing a “simple” PaymentIntent functionality but the complexity / mass of the required n8n UI definition is pure crazy.

The cURL request on the other hand is quite trivial and would look like this for example for one particular payment_method and usecase. Please note the dependent options based on values of previous array levels:

payment_method_data[type]: "customer_balance"
payment_method_types[0]: "customer_balance"
payment_method_options[customer_balance][funding_type]: "bank_transfer"
payment_method_options[customer_balance][bank_transfer][type]: "eu_bank_transfer"
payment_method_options[customer_balance][bank_transfer][eu_bank_transfer][country]: "DE"

Is there any tooling / suggestion / pattern to solve this with n8n better than implementing each and every level of possible options, enums, etc.?

We could - for example - just start and implement the payment_methods we require and leave this as a starting point. Still this will result in a massive n8n node declaration file. I am not sure about maintainability.
We also considered just adding a simple key => value fixedCollection allowing to adding the object structure manually and then crafting a request body from it to avoid the complete specification. Still this feels dirty…

Information on your n8n setup

  • n8n version: 0.178.0
  • Database you’re using (default: SQLite): local dev
  • Running n8n with the execution process [own(default), main]: npm run dev
  • Running n8n via [Docker, npm, n8n.cloud, desktop app]: npm local dev

Happy for any suggestions :slight_smile:

Thank you very much,

Jan

1 Like

Hey @JanTh, I am not exactly an avid node developer myself, but to avoid a single massive file you could consider spreading out your node logic across multiple files.

The Salesforce node for example would have separate separate files for each interface as well as separate descriptions for reach resource, in addition to the usual node.ts and GenericFunctions.ts files.

That said, this still requires implementing the possible options. Perhaps our senior node builders like @RicardoE105 have additional suggestions here?

Hi @MutedJam,

yea, separate files is already implemented for the Stripe Node so this is a no brainer and a good basic start. We checked several of your built in nodes and already got a fair understanding on how you build nodes. We also developed several (private) nodes ourselves already.

But still, there are literally hundreds of possible key/value pairs in complex structures just for the payment method options that would require implementation. I believe this is quite a rare case but still a challenge that will be always around with n8n and the “build a ui for an API” task.

Let’s see if there is any other magic somewhere to make this easier to solve :slight_smile:

I just checked the endpoint, and, as you mentioned, it has a lot of nested fields. Sadly there is no walkaround. In order to get it merged, it will have to have all the possible fields. Look at the Slack node (blocks) and Notion node (blocks). They also have a lot of nested fields.

Have you thought about using the HTTP node to consume this particular endpoint?

Hey @RicardoE105,

the HTTP Node would be the “dump” fallback solution. Just wanted to check if there are better options available.
Also thank you very much for clarifying your merge requirements. So I will not waste any time in this and try to open a PR with a partial implementation.

I was secretly hoping that you have something like a d.ts to n8n converter internally :wink: As the Type definition does already contain all the required information to generate a UI from it. Maybe something to consider? :wink:

Have a great weekend!

Jan

1 Like