n1coePayDocs API reference

n1co.js reference

The loader, the client, the card element, the cvc element, card capture, charging and the errors of n1co.js.

  1. Load n1co.js from the n1co host, on an https page.
  2. Create the client: n1co('pk_…').
  3. Mount the card element and call capture() or confirmPayment().
Minimal page
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>n1co.js</title>
  </head>
  <body>
    <div id="card"></div>
    <script src="https://elements.n1co.dev/v1/n1co.js"></script>
    <script>
      const card = n1co('pk_3x4mpl3pUbl1shabl3k3yAAAAAAAAAAA').elements().create('card');
      card.on('ready', () => console.log('card element ready'));
      card.on('error', (error) => console.error(error.code, error.message));
      card.mount('#card');
    </script>
  </body>
</html>

Loading n1co.js#

Form Path When to use it
Floating /v1/n1co.js Always the latest version. Cached for 5 minutes.
Pinned /v1/n1co-<hash>.js An immutable version, with integrity and crossorigin.
Pinned version with SRI
<script src="https://elements.n1co.dev/v1/n1co-<hash>.js" integrity="sha384-…" crossorigin="anonymous"></script>

Each pinned version will be published in the Changelog. In development, the host is https://elements.n1co.dev.

Your page uses https:// (or localhost for development) and a different origin from n1co.js. Its Content Security Policy allows that host in script-src and frame-src.

n1co(publishableKey)#

Creates the client with your publishable key. It takes no options.

The card element#

n1co('pk_…').elements().create('card', options?) creates the element.

Options#

All are optional; an invalid value throws invalid_options.

Option Values Default
locale 'es', 'en' 'es'
fields.name 'required', 'optional', 'hidden' 'required'
brands Non-empty subset of ['visa', 'mastercard', 'amex'] All three
layout 'stacked', or 'inline' with expiry and code in a row 'stacked'
appearance { theme?: 'light' | 'dark', variables?: { …tokens } } { theme: 'light', variables: {} }
update { brand, last4 } of a saved card: update mode, without the number. Fixed at creation; brands does not apply. None

A number from a brand outside brands is reported as unsupported_brand.

Appearance#

Free-form CSS is not accepted, only these tokens:

Token Values
fontFamily 'system', 'sans-serif', 'serif', 'monospace'
fontSizeBase 12 to 20 px (16 or '16px')
colorText, colorTextPlaceholder, colorBackground, colorBorder, colorBorderFocus, colorDanger '#rgb' or '#rrggbb'
borderRadius 0 to 16 px
spacingUnit 2 to 12 px

colorText and colorDanger need a 3:1 contrast with colorBackground, and colorTextPlaceholder 2:1. With a dark background, use theme: 'dark'.

const card = n1co('pk_3x4mpl3pUbl1shabl3k3yAAAAAAAAAAA')
  .elements()
  .create('card', {
    layout: 'inline',
    brands: ['visa', 'mastercard'],
    appearance: { theme: 'light', variables: { fontFamily: 'system', colorBorderFocus: '#7b3eff', borderRadius: 8 } },
  });

Methods#

All except capture() return the element and can be chained.

Method Effect
mount(selectorOrElement) Inserts the iframe; its height follows the form (40 to 600 px).
unmount() Removes the iframe and discards what was typed.
on(event, handler) Adds a handler.
off(event, handler) Removes a handler.
focus(field?) Focuses 'number', 'expiry', 'cvc' or 'name'. Defaults to 'number' ('expiry' in update mode).
clear() Empties the fields. Ignored during a capture.
update({ appearance?, locale? }) Changes language or appearance. The theme is replaced; variables are merged. The update option cannot change.
capture({ client_secret }) Saves the card. Returns a promise.

mount() throws an N1coError if the page does not meet the requirements. Call focus() and clear() after ready.

Events#

Event Data
ready None. The frame is ready.
change { complete, empty, brand, error }; error is null or { field, code, message }.
focus, blur { field }.
error { code, message }: frame_timeout (10 s) or frame_config_unavailable. You can mount it again.
capture { ok: true, card } or { ok: false, error } for each capture().

change fires when the state changes, not on every keystroke.

capture()#

const result = await card.capture({ client_secret: 'cs_…_secret_…' });
// { ok: true, card: { id: 'card_…', brand: 'visa', last4: '4242', exp_month: 12, exp_year: 2030 } }

client_secret is the one of a card session. During the capture the fields are disabled; on success they are emptied, and another capture responds already_captured until clear(). On failure, the promise rejects with N1coCaptureError.

capture() codes#

Code What happened What to do
incomplete_number, invalid_number, unsupported_brand, incomplete_expiry and other field codes A field is incomplete or invalid; field says which. The buyer fixes it.
card_rejected The card was rejected. Ask for another card.
invalid_request n1co refused a value; field points to it when it can. The buyer fixes the field.
duplicate_field The request repeated a field. Retry.
card_session_not_found, card_session_expired, card_session_completed, card_session_canceled The session no longer works. The fields are emptied. Create a new session.
capture_outcome_unknown n1co could not confirm the capture and canceled the session. Create a new session.
card_session_in_progress Another capture of the session is still running. Wait and retry.
rate_limited Too many attempts. Wait before retrying.
n1co_api_unavailable, capture_not_tokenized, invalid_proxy_key n1co is not available or there is a problem on its side. Retry later.
platform_access_pending Your store is not enabled yet. Check your setup.
origin_not_allowed A configuration problem at n1co. Contact n1co.
page_origin_not_allowed Your page is not in the session's page_origins. Check page_origins.
not_visible The form was covered or off screen. Show the form and retry.
network_error n1co did not respond within 30 s. Read the session on your server before retrying.
unexpected_response n1co answered something n1co.js does not understand. Retry later.
invalid_client_secret The client_secret is missing or malformed. Check what your server hands over.
not_ready The element is not mounted or ready. Wait for ready.
capture_in_progress Another capture() or confirmPayment() with this element has not finished. Wait for it to finish.
already_captured This element already captured a card. Call clear().
capture_timeout The frame did not respond within 45 s. Read the session on your server before retrying.
element_unmounted unmount() was called during the capture. Mount the element again.
card_unavailable The card of the update session no longer exists. The fields are cleared. Save a new card.
number_not_allowed, missing_number The element's mode does not match the session's. The fields are kept. Use update only with update sessions.

The cvc element#

A single field, in n1co's frame, for the security code of a saved card. The code never reaches your page.

const n1 = n1co('pk_3x4mpl3pUbl1shabl3k3yAAAAAAAAAAA');
const cvc = n1.elements().create('cvc', { brand: 'visa', last4: '4242' });
cvc.mount('#cvc');
const intent = await n1.confirmPayment({ client_secret, cvc });
Option Values Default
brand 'visa', 'mastercard', 'amex', 'unknown'. 4 digits with 'amex', 3 with 'visa' and 'mastercard', 3 or 4 with 'unknown'. None: 3 or 4 digits
last4 4 digits, shown as •••• 4242. None
label 'visible', or 'hidden' (still read by screen readers) 'visible'
locale 'es', 'en' 'es'
appearance The card element's tokens. { theme: 'light', variables: {} }
Event or method Difference from the card element
change { complete, empty, error }; error.code is incomplete_cvc or invalid_cvc.
ready, focus, blur, error The same; in focus and blur, field is 'cvc'.
mount, unmount, on, off, focus(), clear(), update() The same.
capture() Rejects with N1coError unsupported: a code alone is never saved.

confirmPayment()#

Pays a payment intent with the card element or with the card your server attached, and shows 3D Secure if the bank asks for it.

const n1 = n1co('pk_3x4mpl3pUbl1shabl3k3yAAAAAAAAAAA');
const intent = await n1.confirmPayment({ client_secret, card }); // new card
const paid = await n1.confirmPayment({ client_secret }); // attached card
const withCode = await n1.confirmPayment({ client_secret, cvc }); // attached card with its code
Option Required Description
client_secret Yes The payment intent's: pi_…_secret_….
card No A card element of this same n1co(), mounted and ready. Without it, the attached card is charged.
cvc No A cvc element of this same n1co(): charges the attached card with its code. Not with card.
billing No { country, state?, postal_code? } for this attempt. Required by US and Canadian cards.

It resolves with the intent in succeeded, processing, requires_payment_method or canceled; see Charge. If n1co is slow, it reads the intent for up to 60 seconds before resolving with processing.

Run one confirmation at a time per client.

confirmPayment() rejections#

It rejects with N1coPaymentError when the attempt could not be made.

Code What happened
incomplete_number, invalid_number and other field codes A field is invalid; field says which. Nothing was sent.
incomplete_cvc, invalid_cvc The cvc element is incomplete or invalid. Nothing was sent.
cvc_required The intent asks for the security code: confirm with cvc. No attempt was used.
cvc_without_saved_card Confirmed with cvc on an intent without an attached card.
invalid_client_secret The client_secret is missing or malformed.
invalid_options Unknown option, invalid billing, card or cvc is not from this client, or card is in update mode.
not_ready The card element is not mounted or ready.
confirm_in_progress Another confirmation of this client has not finished.
already_paid This card element or cvc element already paid; call clear().
payment_method_required No card and no card attached to the intent.
card_unavailable The attached card can no longer be used; confirm with the card element.
invalid_request n1co refused a value; field is a card field or 'billing'. Also card and cvc together.
payment_intent_not_found The client_secret does not exist.
payment_intent_unexpected_state It is already paid, canceled, expired or in 3D Secure. Read it.
payment_intent_in_progress Another confirmation of this intent is running.
payment_intent_requires_reconciliation The outcome could not be known twice; n1co reconciles it. Do not retry.
page_origin_not_allowed Your page is not in the intent's page_origins.
rate_limited More than 10 per minute for this intent, or too many in total.
n1co_api_unavailable, platform_access_pending, capture_not_tokenized, invalid_proxy_key, origin_not_allowed n1co is not available; the attempt was not used up. Retry later.
not_visible The card element was covered or off screen.
network_error n1co did not respond in time (150 s when confirming, 30 s when reading).
unexpected_response n1co answered something n1co.js does not understand.
payment_timeout The payment frame did not respond. Read the intent on your server before retrying.
element_unmounted The card element was unmounted during the payment.
frame_timeout, frame_config_unavailable The payment frame could not start.
unsupported_page_origin, insecure_page, invalid_frames_origin The page cannot load the frames (the mount() rules).

retrievePaymentIntent()#

const intent = await n1.retrievePaymentIntent(client_secret);

Reads the intent to show the amount or the attached card before confirming. Your page sees a reduced version:

Field Value
id, object pi_…; 'payment_intent'.
status One of the five intent states.
amount, currency Minor units and ISO 4217 code.
description Your description, or null.
payment_method { brand, last4, exp_month, exp_year, saved }, or null.
next_action Always null: n1co.js takes care of 3D Secure.
last_error { code, decline_code, message }, with message translated, or null.
attempts_remaining Confirmations left.
expires_at When it is canceled if not paid.
cvc_required true when charging the attached card needs the security code (cvc).

It never includes metadata, reference, billing, card ids, order_id or authorization_code.

Errors#

Type When Fields
N1coError Thrown on invalid arguments or on a page that is not valid. code, message
error event The frame did not start. code, message
N1coCaptureError Rejection of capture(). code, message, field?
N1coPaymentError Rejection of confirmPayment() and retrievePaymentIntent(). code, message, field?

Decide with code, which is stable; message comes translated and can be shown.

N1coError code When
invalid_publishable_key The key is not pk_ and 32 base64url characters.
invalid_options Unknown or invalid options.
unsupported_element_type An element type other than 'card' and 'cvc'.
unsupported capture() on a cvc element.
invalid_frames_origin The page shares its origin with the n1co.js host.
insecure_page The page is http:// and is not localhost or 127.0.0.1.
unsupported_page_origin The page has no http(s):// origin, for example file:.

Browsers#

Current versions of Chrome, Edge, Firefox and Safari. not_visible only works with IntersectionObserver v2.