n1co.js reference
The loader, the client, the card element, the cvc element, card capture, charging and the errors of n1co.js.
- Load
n1co.jsfrom the n1co host, on anhttpspage. - Create the client:
n1co('pk_…'). - Mount the card element and call
capture()orconfirmPayment().
<!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. |
<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.