# Customization

Configure `<rebill-checkout>` through attributes. Swap sections on or off, inject custom CSS, pre-fill customer data, pre-apply a coupon, and drive submission from your own UI. An interactive SDK playground is coming soon.

## Attributes

| Attribute              | Type          | Required            | Notes                                                                                                                         |
| ---------------------- | ------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `public-key`           | string        | Yes                 | Your organization's `pk_` key from the dashboard. Safe to expose in the browser.                                              |
| `product-id`           | string        | See note            | ID of a stored product for a one-time charge.                                                                                 |
| `plan-id`              | string        | See note            | ID of a stored plan for a subscription.                                                                                       |
| `instant-product`      | object (JSON) | See note            | Inline product for dynamic pricing. See [Instant Checkout](/sdk/instant-checkout).                                            |
| `instant-plan`         | object (JSON) | See note            | Inline plan for dynamic recurring pricing. See [Instant Checkout](/sdk/instant-checkout).                                     |
| `customer-information` | object (JSON) | No                  | Pre-fills or overrides customer data. Required when you hide `customerInformation` or `billingAddress` sections. Shape below. |
| `coupon-code`          | string        | No                  | Pre-applies a coupon code before the form renders. Customer still sees the applied discount in the summary.                   |
| `language`             | string        | No                  | `'en' \| 'es' \| 'pt'`. Defaults to the session's country language.                                                           |
| `one-click-checkout`   | boolean       | No (default `true`) | Offers one-click payment to returning customers with a saved card.                                                            |
| `display`              | object (JSON) | No                  | Section visibility. Shape below.                                                                                              |
| `css`                  | string        | No                  | Custom CSS (inline string or URL to a stylesheet).                                                                            |
| `js`                   | string        | No                  | Custom JavaScript to inject (string or URL). Use with care.                                                                   |

One of `product-id`, `plan-id`, `instant-product`, or `instant-plan` is required. Pick the one that matches your flow.

## `display` — show or hide checkout sections

All flags default to `true`. Flip to `false` to hide.

| Flag                    | Controls                                                                                             |
| ----------------------- | ---------------------------------------------------------------------------------------------------- |
| `submitButton`          | The default submit button. Set to `false` to drive submission via `submit()`.                        |
| `checkoutSummary`       | The right-hand summary panel (amount, item name, coupon recap).                                      |
| `billingAddress`        | The billing address section. Data must come from `customer-information` when hidden.                 |
| `customerInformation`   | Name, email, phone, identification. Data must come from `customer-information` when hidden.          |
| `discountCode`          | Coupon code input. Hiding it doesn't block pre-applied `coupon-code`.                                |
| `logo`                  | Your organization logo at the top of the checkout.                                                   |
| `footer`                | The Rebill-branded footer.                                                                           |
| `processingPayment`     | The in-progress loader while the processor responds.                                                 |
| `successPage`           | The built-in "thank you" page after `success`. Turn off to redirect or render your own.              |
| `errorMessage`          | The built-in error banner. Turn off to render errors from the `error` event.                         |
| `useAddressSearch`      | The autocomplete search input for the billing address. When `false`, shows the manual form directly. |
| `sandboxMode`           | Sandbox-only helper UI (test card shortcuts, doc links). Hide in production previews.                |
| `excludePaymentMethods` | Array of methods to hide. Accepts `'card'`, `'cash'`, `'bank_transfer'`.                             |

### Default `display` values

```javascript
{
  submitButton: true,
  checkoutSummary: true,
  billingAddress: true,
  customerInformation: true,
  discountCode: true,
  logo: true,
  footer: true,
  processingPayment: true,
  successPage: true,
  errorMessage: true,
  useAddressSearch: true,
  sandboxMode: true
  // excludePaymentMethods is undefined by default — no methods are filtered
}
```

## Pre-filling customer data

When you hide `customerInformation` or `billingAddress`, pass the equivalent data through `customer-information`. The component reads from this object at submit time.

```javascript
customerInformation={{
  // Required when display.customerInformation is false
  email: "ana.perez@rebill.com",
  fullName: "Ana Perez",
  phoneNumber: {
    number: "1123456789",
    countryCode: "AR"
  },
  // Optional: prefills identification fields when the country needs them
  documentType: "DNI",
  documentNumber: "12345678",
  // Required when display.billingAddress is false
  address: {
    billingAddress: {
      address: "Av. Córdoba 123",
      city: "Mar del Plata",
      state: "Buenos Aires",
      country: "AR",
      zip: "7600"
    }
  }
}}
```

`fullName` can't contain digits — a name with numbers returns a `400` at submit time (`customer.firstName: firstName must not contain numeric characters`).

`countryCode` inside `phoneNumber` is the ISO alpha-2 country (`"AR"`, `"US"`, `"BR"`); the SDK resolves it to the dial prefix. `documentType` depends on the country — `DNI` for AR, `CURP` or `RFC` for MX, `CPF` for BR, `CC` or `CE` for CO, `RUT` for CL.

## Driving submission externally

Hide the built-in button and trigger the checkout from your own CTA. Useful for multi-step forms where Rebill is one of several final steps.

```javascript
<rebill-checkout
  ref={checkoutRef}
  public-key="pk_your_public_key"
  plan-id="pln_your_plan_id"
  display='{"submitButton": false}'
/>

// From your own button handler:
async function handleSubmit() {
  try {
    await checkoutRef.current.submit()
  } catch (error) {
    // submit() rejects when the form is invalid — the error event
    // will fire separately with a reason if the charge itself fails.
  }
}
```

## Styling with `css`

```html
<rebill-checkout
  public-key="pk_your_public_key"
  plan-id="pln_your_plan_id"
  css=".rebill-submit-button { background: #111; border-radius: 8px; }"
></rebill-checkout>
```

Pass a string of CSS or a URL to a stylesheet. The styles apply inside the component's shadow DOM; they don't leak to your page and your page's global CSS doesn't leak into the component.

## Events

The component emits seven events. Attach listeners with `addEventListener` — the event's detail payload goes in `event.detail`.

| Event                   | `event.detail`                        | Fires when                                                                                                                            |
| ----------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `ready`                 | `void`                                | The component finished mounting, fetched the session, and is ready for input.                                                         |
| `success`               | `{ paymentMethod, data }`             | Charge was approved by the processor. See [Checkout](/sdk/checkout#what-arrives-on-success) for `data.result` shape.                  |
| `error`                 | `{ paymentMethod, data }`             | Charge was rejected. `data.result?.statusDetail` holds the reason.                                                                    |
| `formChange`            | `{ data, isValid, errors? }`          | Any field value changes. Useful for syncing your external submit button's enabled state.                                              |
| `paymentMethodSelected` | `'card' \| 'cash' \| 'bank_transfer'` | Customer switches the selected method tab.                                                                                            |
| `sessionClosed`         | `{ customerId?, reason }`             | Customer exits the one-click session (e.g., clicks "Use a different card").                                                           |
| `successRedirect`       | Processor-specific payload            | A redirect URL is about to take over (APMs that bounce to a bank, 3DS challenges). Fires in addition to `success`, not instead of it. |

### Listener example

```javascript
const checkout = document.querySelector('rebill-checkout')

checkout.addEventListener('success', (event) => {
  const { paymentMethod, data } = event.detail
  // Fulfill access, then confirm server-side via GET /v3/payments/:id
})

checkout.addEventListener('error', (event) => {
  const { data } = event.detail
  const reason = data.result?.statusDetail ?? data.error?.error?.message
  showRetryPrompt(reason)
})

checkout.addEventListener('formChange', (event) => {
  const { isValid } = event.detail
  myExternalCta.disabled = !isValid
})

checkout.addEventListener('paymentMethodSelected', (event) => {
  track('checkout_method_switched', { method: event.detail })
})
```

## Common mistakes

* **Hiding a section without providing the equivalent data.** If you hide `billingAddress` but don't pass `customer-information.address.billingAddress`, the session fails with a validation error when the customer submits.
* **Injecting untrusted strings into `js`.** The `js` attribute runs arbitrary code inside the component. Only use it with code you authored.
* **Listening only for `success`.** `paymentMethodSelected` and `sessionClosed` are essential for analytics and one-click UX — without them you lose visibility into why customers drop off or switch methods.
* **Assuming `submitButton: false` disables the form.** It only hides the button. The form is still interactive; drive submission with `submit()` or the form stays idle.

## Next

* [Checkout](/sdk/checkout) — full `success` payload and multi-currency behavior.
* [Card tokenization](/sdk/card-tokenization) — when you want to save a card without charging.
* [Renew subscription card](/sdk/renew-subscription-card) — dedicated component for card renewal.
