@fluid-app/fluid-cli-payments
Fluid CLI plugin for payments onboarding: the KYC form at
Settings → Onboarding in the admin. See what's missing, fill in fields and
documents, and submit the form for review. Once payments are set up,
test-order places one order on the company's test gateway.
npm install -g @fluid-app/fluid-cli @fluid-app/fluid-cli-payments
fluid login
fluid payments onboarding show # status, steps, and every required field still missing
fluid payments onboarding fields --required # keys, types, options, and when each is required
fluid payments onboarding options mcc-codes # also business-types (--country US), countries, currencies
fluid payments onboarding set --yes \
--set info.user_has_authority=true --set info.user_is_signatory=true \
--set entity.legal_name="Acme Inc" --set entity.country_iso=US \
--file entity.business_license=./license.pdf
fluid payments onboarding set --yes --file owner.government_issued_ids=./passport.jpg --id-type passport
fluid payments onboarding set --yes --owner new --set owner.full_name="Sam Lee" --set owner.is_beneficial_owner=true
fluid payments onboarding set --yes --set country.US.currency=USD --set country.US.settlement_currency=USD \
--set country.US.entity_legally_registered=true
fluid payments onboarding remove owner 42 --yes # or entity, bank, or a country by ISO code
fluid payments onboarding submit --accept-terms --yes
Prefer answering question by question? fluid payments onboarding walk asks
for each missing field in form order and saves each answer as you go. Type
< to go back, > to skip, or ? for the menu. From the menu you can jump to
any step, change a saved answer, or submit. Pick lists cover yes/no, countries,
currencies, MCC codes, and business types. Sensitive answers are hidden as you
type. --step <id> starts at a step. It needs a terminal; scripts and agents
use show and set.
show and set return a missing list. Each entry names the step, the
field, why it's needed, and a fix: the set flags that resolve it, such as
--entity 12 --set entity.website=<value>. readyToSubmit: true means
submit will go through.
Fields go to records:
info.*andunderwriting.*are the company's answers.entity.*goes to the primary legal entity, or--entity <id|new>.bank.*goes to the primary bank account, or--bank <id|new>.owner.*goes to the onboarding contact (the person filling in the form), or--owner <id|new>.country.<ISO>.*adds or updates a country the company sells in.
A record that doesn't exist yet is created. The first legal entity and bank account become primary, and the first person becomes the onboarding contact.
Documents upload with --file key=path, up to 10 MB each. Multi-file
documents add to what's there unless you pass --replace-files. Policies and
agreements also take a URL: --set underwriting.privacy_policy.link=https://....
submit marks every step complete and accepts Fluid's payments terms for
the company. That's why it needs --accept-terms as well as --yes. It
refuses while anything is missing. The acceptance records the person who
signed, so it needs a person's sign-in (fluid login with email). With a
company API token, submit writes nothing and returns
status: "ready_to_submit" with submitUrl, the admin's onboarding form,
where a person submits.
Tax IDs, account and routing numbers, ID numbers, and dates of birth are
masked in every output. Uploaded documents are named, never linked. Every
command prints JSON. Failures print a JSON error on stderr and exit
non-zero. Commands that change data ask for confirmation unless you pass
--yes.
The walkthrough is the payments onboarding guided setup at https://docs.fluid.app/setup.
Test order
test-order proves checkout works for a new company by placing one order on
its test gateway, with you as the buyer:
fluid payments test-order --product 501 --accept-agreements --yes
fluid payments test-order --variant 9001 --country CA --accept-agreements --yes \
--address '{"address1":"100 King St W","city":"Toronto","state":"ON","postal_code":"M5X 1A9"}'
The buyer is the signed-in person: the order uses your email, and --email
can only repeat it. Checkout records the store's required agreements as
accepted by the buyer, so a test order needs a person's sign-in (fluid login
with email) and refuses a company API token with PERSON_SIGN_IN_REQUIRED.
When the store has required agreements, it stops with
AGREEMENTS_NOT_ACCEPTED and their titles until you read them and pass
--accept-agreements.
It builds a cart for one unit (--product buys the product's master
variant, so a draft product works too), sets the email, address and the
first shipping method, then pays with the test card 4242 4242 4242 4242
and prints the order's id and number as JSON. The built-in address is in the US. Outside
the US, pass a real --address, since tax is quoted for it.
Before anything is paid for, it checks that every payment method the cart
offers is a test card on the Bogus gateway, all on one payment account, and
charges only that account. Otherwise it stops with a code, such as
NO_PAYMENT_ACCOUNT (a company that signed up recently may need to confirm
its signup first) or NOT_TEST_GATEWAY. A bad email or address also fails before
anything is paid for. It names the agreements you accept in the question and
the output, and sends back the version of their text it was shown, so
checkout refuses if the wording changes before the order completes. Agents pass --yes, and people at a
terminal are asked; without either it stops with CONFIRMATION_REQUIRED,
and a "no" stops with CANCELLED. Just before the order completes it reads
the cart again and repeats the payment checks, stopping with
PAYMENT_ACCOUNT_CHANGED if the account it checked is no longer the one
the cart would charge. Use the same environment as your login
(--base-url).
The order is real, though no money moves. The confirmation email goes to
you, order webhooks fire, and inventory is adjusted as for any order.
Checkout finds or creates a customer (and member) for your email in the
store and records the agreement acceptances against it. Nothing marks the
order as a test, so it shows in sales reports until it's refunded. Refund
and cancel it in the admin if you don't want it in the order list. Each run
tries once and places a new order. A failure after the cart exists gives
the cart's cartId and the time in details (never the cart token, which
opens the cart). If it fails with ORDER_OUTCOME_UNKNOWN, look in the
admin for an order from your email at that time before running it again.