webpay-api

Integrate the Transbank Webpay Plus payment gateway using its REST API (HTTP). Use this skill whenever the user needs to implement Webpay Plus payments, create payment transactions, confirm payments, refund/reverse transactions, check transaction status, or capture deferred payments via the Webpay Plus API. Also use this skill when the user mentions Transbank, Webpay, Chilean payment processing, payment integration for Chile, or needs test credentials for Webpay Plus integration environment.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "webpay-api" with this command: npx skills add xoverlap/webpay-skill/xoverlap-webpay-skill-webpay-api

Webpay Plus - REST API Integration Skill

This skill provides everything needed to integrate the Transbank Webpay Plus payment gateway using its REST API (HTTP). It covers the complete purchase cycle: creating transactions, confirming payments, checking status, refunding/reversing, and deferred capture.

This skill covers Webpay Plus only (single-store). It does NOT cover Webpay Plus Mall (multi-store) or Oneclick.

Table of Contents

  1. Environments and Credentials
  2. Payment Flow Overview
  3. API Endpoints
  4. Reference Tables
  5. Error Codes
  6. Going to Production

Environments and Credentials

The Webpay REST API is secured via TLSv1.2 and authenticated using two HTTP headers on every request:

HeaderDescription
Tbk-Api-Key-IdCommerce code (codigo de comercio)
Tbk-Api-Key-SecretSecret key (llave secreta)

All requests must also include Content-Type: application/json.

Environments

EnvironmentBase URL
Integration (testing)https://webpay3gint.transbank.cl
Productionhttps://webpay3g.transbank.cl

Integration Test Credentials

Use these credentials freely for testing in the integration environment:

Tbk-Api-Key-Id: 597055555532
Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C

Test Cards for Integration

For testing in the integration environment, use the test cards documented at https://www.transbankdevelopers.cl/documentacion/como_empezar#ambientes

Common test data for a successful transaction:

  • Card number: 4051 8856 0044 6623
  • Expiration date: Any future date
  • CVV: 123
  • RUT: 11.111.111-1
  • Password: 123

To simulate a rejected transaction, use RUT 11.111.111-1 with password 123 but reject the payment in the Webpay form.

Commerce Codes for Integration

ProductCommerce Code
Webpay Plus597055555532
Webpay Plus (Deferred Capture)597055555540

Payment Flow Overview

The Webpay Plus payment cycle follows this sequence:

1. MERCHANT SERVER                    2. WEBPAY (Transbank)
   |                                     |
   |-- POST /transactions -------------->|  (Create transaction)
   |<-- { token, url } ------------------|
   |                                     |
   |-- Redirect user to url + token ---->|  (User pays on Webpay form)
   |                                     |
   |<-- Redirect to return_url ----------|  (Webpay sends token_ws via POST)
   |                                     |
   |-- PUT /transactions/{token} ------->|  (Confirm / Commit transaction)
   |<-- { transaction result } ----------|
   |                                     |
   |-- Show result to user              |

Step-by-step:

  1. Create transaction: Your server calls POST /rswebpaytransaction/api/webpay/v1.2/transactions with the order details. You receive a token and a url.

  2. Redirect to Webpay: Redirect the user's browser to the returned url, passing the token via a form POST field called token_ws:

    <form method="POST" action="{url}">
      <input type="hidden" name="token_ws" value="{token}">
      <input type="submit" value="Pagar">
    </form>
    
  3. User pays: The user enters their card details on Transbank's secure form and authorizes the payment.

  4. Webpay redirects back: After authorization (or rejection/abort), Webpay redirects the user back to your return_url via POST, sending:

    • token_ws: The transaction token (if the user completed the flow)
    • TBK_TOKEN + TBK_ORDEN_COMPRA + TBK_ID_SESION: Only if the user aborted the payment
  5. Confirm transaction: Your server calls PUT /rswebpaytransaction/api/webpay/v1.2/transactions/{token} to confirm and get the result.

  6. Show result: Display the payment result to the user.

Handling Aborted Payments

If the user clicks "Anular" (cancel) on the Webpay form, the redirect to return_url will include TBK_TOKEN, TBK_ORDEN_COMPRA, and TBK_ID_SESION instead of token_ws. In this case, the transaction was NOT completed. Do not call commit; inform the user that payment was cancelled.

Timeout Behavior

If the user does not complete the payment within the allowed time, two requests arrive at return_url:

  1. First with TBK_TOKEN, TBK_ORDEN_COMPRA, TBK_ID_SESION (and empty token_ws)
  2. A second request with just TBK_TOKEN (a POST from the user's browser)

Both indicate the transaction was abandoned. Do not confirm the transaction.


API Endpoints

All endpoint paths are relative to the base URL for the chosen environment.

Base path: /rswebpaytransaction/api/webpay/v1.2

1. Create Transaction

Initialize a Webpay Plus payment. Returns a token and URL for the payment form.

Endpoint: POST /rswebpaytransaction/api/webpay/v1.2/transactions

Request Headers:

Tbk-Api-Key-Id: 597055555532
Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C
Content-Type: application/json

Request Body:

{
  "buy_order": "ordenCompra12345678",
  "session_id": "sesion1234557545",
  "amount": 10000,
  "return_url": "http://www.comercio.cl/webpay/retorno"
}

Request Parameters:

ParameterTypeDescription
buy_orderStringUnique order ID for this transaction. Max length: 26. Allowed chars: letters, numbers, and |_=&%.,~:/?[+!@()>-
session_idStringSession identifier, for internal use by the merchant. Returned at the end of the transaction. Max length: 61
amountDecimalTransaction amount. Integer for CLP, max 2 decimals for USD. Max length: 17
return_urlStringURL where Webpay redirects after authorization. Max length: 256

Response (200 OK):

{
  "token": "e9d555262db0f989e49d724b4db0b0af367cc415cde41f500a776550fc5fddd3",
  "url": "https://webpay3gint.transbank.cl/webpayserver/initTransaction"
}

Response Fields:

FieldTypeDescription
tokenStringTransaction token. Length: 64
urlStringWebpay payment form URL. Max length: 255

2. Confirm Transaction (Commit)

After the user completes payment on Webpay and is redirected to return_url, confirm the transaction. This is mandatory to finalize the payment.

Endpoint: PUT /rswebpaytransaction/api/webpay/v1.2/transactions/{token}

Request Headers:

Tbk-Api-Key-Id: 597055555532
Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C
Content-Type: application/json

URL Parameters:

ParameterTypeDescription
tokenStringTransaction token (in the URL path, not body). Length: 64

No request body is needed.

Response (200 OK):

{
  "vci": "TSY",
  "amount": 10000,
  "status": "AUTHORIZED",
  "buy_order": "ordenCompra12345678",
  "session_id": "sesion1234557545",
  "card_detail": {
    "card_number": "6623"
  },
  "accounting_date": "0522",
  "transaction_date": "2019-05-22T16:41:21.063Z",
  "authorization_code": "1213",
  "payment_type_code": "VN",
  "response_code": 0,
  "installments_number": 0
}

Response Fields:

FieldTypeDescription
vciStringCardholder authentication result. See VCI Codes
amountDecimalTransaction amount. Max length: 17
statusStringTransaction status. See Transaction Statuses
buy_orderStringOrder ID sent in create. Max length: 26
session_idStringSession ID sent in create. Max length: 61
card_detailObjectCard details object
card_detail.card_numberStringLast 4 digits of the card. Max length: 19
accounting_dateStringAuthorization date. Length: 4, format: MMDD
transaction_dateStringAuthorization date/time. ISO 8601 format
authorization_codeStringAuthorization code. Max length: 6
payment_type_codeStringPayment type. See Payment Type Codes
response_codeNumberAuthorization response code. 0 = approved
installments_amountNumberInstallment amount. Max length: 17
installments_numberNumberNumber of installments. Max length: 2
balanceNumberRemaining balance for a nullified detail. Max length: 17

Validating a Successful Transaction

After calling commit, verify the transaction was successful by checking:

  1. response_code equals 0
  2. status equals "AUTHORIZED"

If response_code is not 0, the transaction was rejected.


3. Get Transaction Status

Query the state of a transaction at any time. Useful for error recovery or verifying a transaction's current state.

Endpoint: GET /rswebpaytransaction/api/webpay/v1.2/transactions/{token}

Request Headers:

Tbk-Api-Key-Id: 597055555532
Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C
Content-Type: application/json

URL Parameters:

ParameterTypeDescription
tokenStringTransaction token (in URL, not body). Length: 64

Response: Same structure as Commit response (see above).


4. Refund / Reverse Transaction

Refund all or part of a completed transaction. If called within the same day as the original transaction, it may result in a reversal (REVERSED). If called on a different day, it becomes a nullification (NULLIFIED).

Endpoint: POST /rswebpaytransaction/api/webpay/v1.2/transactions/{token}/refunds

Request Headers:

Tbk-Api-Key-Id: 597055555532
Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C
Content-Type: application/json

URL Parameters:

ParameterTypeDescription
tokenStringTransaction token (in URL, not body). Length: 64

Request Body:

{
  "amount": 1000
}

Request Parameters:

ParameterTypeDescription
amountDecimalAmount to refund/reverse. Integer for CLP, max 2 decimals for USD. Max length: 17

Response (200 OK) - Nullification:

{
  "type": "NULLIFIED",
  "authorization_code": "123456",
  "authorization_date": "2019-03-20T20:18:20Z",
  "nullified_amount": 1000.00,
  "balance": 0.00,
  "response_code": 0
}

Response (200 OK) - Reversal:

{
  "type": "REVERSED"
}

Response Fields:

FieldTypeDescription
typeStringRefund type: REVERSED or NULLIFIED. Max length: 10
authorization_codeString(NULLIFIED only) Authorization code. Max length: 6
authorization_dateString(NULLIFIED only) Authorization date/time
balanceDecimal(NULLIFIED only) Updated balance. Max length: 17
nullified_amountDecimal(NULLIFIED only) Amount nullified. Max length: 17
response_codeNumber(NULLIFIED only) Result code. 0 = success. Max: 2

Refund Error Codes:

CodeDescription
304Null input field validation
245Commerce code does not exist
22Commerce is not active
316Commerce does not match certificate
308Operation not allowed
274Transaction not found
16Transaction does not allow nullification
292Transaction is not authorized
284Nullification period exceeded
310Transaction already nullified
311Amount exceeds available balance to nullify
312Generic nullification error
315Authorizer error
53Transaction does not allow partial nullification with installments

5. Capture Transaction (Deferred)

For merchants configured with deferred capture, this endpoint captures a previously authorized transaction. Requires a specific commerce code for deferred capture.

Integration commerce code for deferred capture: 597055555540

Endpoint: PUT /rswebpaytransaction/api/webpay/v1.2/transactions/{token}/capture

Request Headers:

Tbk-Api-Key-Id: 597055555540
Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C
Content-Type: application/json

URL Parameters:

ParameterTypeDescription
tokenStringTransaction token (in URL, not body). Length: 64

Request Body:

{
  "buy_order": "415034240",
  "authorization_code": "12345",
  "capture_amount": 1000
}

Request Parameters:

ParameterTypeDescription
buy_orderStringOrder ID of the transaction to capture. Max length: 26
authorization_codeStringAuthorization code from the original transaction. Max length: 6
capture_amountDecimalAmount to capture. Max length: 17

Response (200 OK):

{
  "token": "e074d38c628122c63e5c0986368ece22974d6fee1440617d85873b7b4efa48a3",
  "authorization_code": "123456",
  "authorization_date": "2019-03-20T20:18:20Z",
  "captured_amount": 1000,
  "response_code": 0
}

Response Fields:

FieldTypeDescription
tokenStringTransaction token. Max length: 64
authorization_codeStringDeferred capture authorization code. Max length: 6
authorization_dateStringAuthorization date/time
captured_amountDecimalCaptured amount. Max length: 6
response_codeNumberResult code. 0 = success. Max: 2

Capture Error Codes:

CodeDescription
304Null input field validation
245Commerce code does not exist
22Commerce is not active
316Commerce does not match certificate
308Operation not allowed
274Transaction not found
16Transaction is not deferred capture
292Transaction is not authorized
284Capture period exceeded
310Transaction previously reversed
309Transaction previously captured
311Capture amount exceeds authorized amount
315Authorizer error

Reference Tables

Transaction Statuses

StatusDescription
INITIALIZEDTransaction has been created, waiting for user to complete payment
AUTHORIZEDTransaction was authorized successfully
REVERSEDTransaction was reversed (same-day refund)
FAILEDTransaction was rejected or failed
NULLIFIEDTransaction was nullified (refund after accounting date)
PARTIALLY_NULLIFIEDTransaction was partially nullified
CAPTUREDTransaction was captured (deferred capture)

Payment Type Codes

CodeDescription
VDDebit Sale (Venta Debito)
VNNormal Sale - Credit (Venta Normal)
VCInstallment Sale (Venta en Cuotas)
SI3 interest-free installments (3 Cuotas sin Interes)
S22 interest-free installments (2 Cuotas sin Interes)
NCN interest-free installments (N Cuotas sin Interes)
VPPrepaid Sale (Venta Prepago)

VCI Codes

The vci field indicates cardholder authentication results. This is supplementary information to response_code. Merchants should NOT validate this field as new codes are constantly added.

Domestic transactions:

CodeDescription
TSYAuthentication successful
TSNAuthentication rejected
NPNon-participating, no authentication
U3Connection failure, authentication rejected
INVInvalid data
AAttempted
CNP1Commerce does not participate
EOPOperational error
BNABIN not enrolled
ENAIssuer not enrolled

Foreign sale codes:

CodeDescription
TSYSSuccessful frictionless authentication
TSASAttempt, card not enrolled / issuer unavailable
TSNSFailed, not authenticated, denied
TSRSAuthentication rejected, frictionless
TSUSAuthentication failed due to technical issue
TSCFChallenge authentication (not accepted by commerce)
TSYFSuccessful challenge authentication
TSNFNot authenticated, denied with challenge
TSUFChallenge authentication failed due to technical issue
NPCCommerce does not participate
NPBBIN does not participate
NPCBCommerce and BIN do not participate
SPCBCommerce and BIN participate, authorization incomplete

Error Codes

HTTP Status Codes

HTTP CodeDescription
200Operation executed successfully
204DELETE operation executed successfully
400Invalid JSON message (malformed or unexpected field)
401Unauthorized. Invalid API Key and/or API Secret
404Transaction not found
405Method not allowed
406Cannot process response in requested format
415Message type not allowed
422Request cannot be processed (data validation or business logic)
500Unexpected error

All errors return a JSON body:

{
  "error_message": "token is required"
}

Going to Production

To move from integration to production:

  1. Complete the certification process with Transbank
  2. Obtain your production commerce code and API secret
  3. Change the base URL from https://webpay3gint.transbank.cl to https://webpay3g.transbank.cl
  4. Replace the integration credentials with your production credentials

More details at https://www.transbankdevelopers.cl/documentacion/como_empezar#puesta-en-produccion


Implementation Examples

Node.js / Express Backend Example

const express = require('express');
const axios = require('axios');

const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Configuration
const WEBPAY_BASE_URL = 'https://webpay3gint.transbank.cl'; // Use production URL for prod
const API_KEY_ID = '597055555532';
const API_KEY_SECRET = '579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C';

const headers = {
  'Tbk-Api-Key-Id': API_KEY_ID,
  'Tbk-Api-Key-Secret': API_KEY_SECRET,
  'Content-Type': 'application/json'
};

// Step 1: Create transaction
app.post('/api/webpay/create', async (req, res) => {
  try {
    const { buy_order, session_id, amount, return_url } = req.body;

    const response = await axios.post(
      `${WEBPAY_BASE_URL}/rswebpaytransaction/api/webpay/v1.2/transactions`,
      { buy_order, session_id, amount, return_url },
      { headers }
    );

    // Return token and url to frontend
    res.json(response.data);
  } catch (error) {
    res.status(error.response?.status || 500).json({
      error: error.response?.data || 'Error creating transaction'
    });
  }
});

// Step 2: Confirm transaction (return_url handler)
app.post('/api/webpay/confirm', async (req, res) => {
  try {
    const token_ws = req.body.token_ws;

    // Check if payment was aborted
    if (!token_ws || req.body.TBK_TOKEN) {
      return res.redirect('/payment-cancelled');
    }

    const response = await axios.put(
      `${WEBPAY_BASE_URL}/rswebpaytransaction/api/webpay/v1.2/transactions/${token_ws}`,
      null,
      { headers }
    );

    const result = response.data;

    // Validate successful transaction
    if (result.response_code === 0 && result.status === 'AUTHORIZED') {
      // Payment successful - update your database
      res.redirect(`/payment-success?order=${result.buy_order}`);
    } else {
      // Payment rejected
      res.redirect(`/payment-rejected?order=${result.buy_order}`);
    }
  } catch (error) {
    res.redirect('/payment-error');
  }
});

// Check transaction status
app.get('/api/webpay/status/:token', async (req, res) => {
  try {
    const response = await axios.get(
      `${WEBPAY_BASE_URL}/rswebpaytransaction/api/webpay/v1.2/transactions/${req.params.token}`,
      { headers }
    );
    res.json(response.data);
  } catch (error) {
    res.status(error.response?.status || 500).json({
      error: error.response?.data || 'Error checking status'
    });
  }
});

// Refund transaction
app.post('/api/webpay/refund', async (req, res) => {
  try {
    const { token, amount } = req.body;

    const response = await axios.post(
      `${WEBPAY_BASE_URL}/rswebpaytransaction/api/webpay/v1.2/transactions/${token}/refunds`,
      { amount },
      { headers }
    );
    res.json(response.data);
  } catch (error) {
    res.status(error.response?.status || 500).json({
      error: error.response?.data || 'Error refunding transaction'
    });
  }
});

Frontend Redirect Example

<!-- After receiving token and url from your backend -->
<form id="webpay-form" method="POST" action="">
  <input type="hidden" name="token_ws" id="token_ws">
  <button type="submit">Pagar con Webpay</button>
</form>

<script>
async function initiatePayment(orderData) {
  const response = await fetch('/api/webpay/create', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      buy_order: orderData.orderId,
      session_id: orderData.sessionId,
      amount: orderData.amount,
      return_url: window.location.origin + '/api/webpay/confirm'
    })
  });

  const { token, url } = await response.json();

  // Redirect to Webpay payment form
  const form = document.getElementById('webpay-form');
  form.action = url;
  document.getElementById('token_ws').value = token;
  form.submit();
}
</script>

cURL Examples

Create transaction:

curl -X POST "https://webpay3gint.transbank.cl/rswebpaytransaction/api/webpay/v1.2/transactions" \
  -H "Tbk-Api-Key-Id: 597055555532" \
  -H "Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C" \
  -H "Content-Type: application/json" \
  -d '{
    "buy_order": "order123",
    "session_id": "session456",
    "amount": 10000,
    "return_url": "http://localhost:3000/webpay/confirm"
  }'

Confirm transaction:

curl -X PUT "https://webpay3gint.transbank.cl/rswebpaytransaction/api/webpay/v1.2/transactions/{token}" \
  -H "Tbk-Api-Key-Id: 597055555532" \
  -H "Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C" \
  -H "Content-Type: application/json"

Get transaction status:

curl -X GET "https://webpay3gint.transbank.cl/rswebpaytransaction/api/webpay/v1.2/transactions/{token}" \
  -H "Tbk-Api-Key-Id: 597055555532" \
  -H "Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C" \
  -H "Content-Type: application/json"

Refund:

curl -X POST "https://webpay3gint.transbank.cl/rswebpaytransaction/api/webpay/v1.2/transactions/{token}/refunds" \
  -H "Tbk-Api-Key-Id: 597055555532" \
  -H "Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C" \
  -H "Content-Type: application/json" \
  -d '{"amount": 5000}'

Capture (deferred):

curl -X PUT "https://webpay3gint.transbank.cl/rswebpaytransaction/api/webpay/v1.2/transactions/{token}/capture" \
  -H "Tbk-Api-Key-Id: 597055555540" \
  -H "Tbk-Api-Key-Secret: 579B532A7440BB0C9079DED94D31EA1615BACEB56610332264630D42D0A36B1C" \
  -H "Content-Type: application/json" \
  -d '{
    "buy_order": "order123",
    "authorization_code": "123456",
    "capture_amount": 10000
  }'

Important Implementation Notes

  1. The buy_order must be unique for each transaction. It cannot be reused.

  2. Always confirm (commit) the transaction after receiving the redirect. If you don't call commit, the transaction remains in INITIALIZED state and the payment will not be processed.

  3. Commit has a time limit: You must confirm the transaction within a few seconds after the user is redirected back. If too much time passes, the transaction may expire.

  4. Handle all redirect scenarios at your return_url:

    • token_ws present: Normal flow, proceed to commit
    • TBK_TOKEN present (no token_ws): User aborted
    • Both present with empty token_ws: Timeout
  5. Refund vs Reversal: The API automatically determines whether to reverse (same day, before accounting cutoff) or nullify (after accounting cutoff). You always call the same endpoint.

  6. Partial refunds are supported: You can refund any amount up to the original transaction amount. Multiple partial refunds are allowed until the balance reaches zero.

  7. Deferred capture requires a special commerce code and configuration with Transbank. Not all merchants have this feature enabled.

  8. The vci field should NOT be used for business logic validation. Use response_code instead. The vci field is informational only and new values are added without documentation updates.

  9. The response_code is the definitive indicator of whether a transaction was approved (0) or rejected (non-zero).

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

sileo-react-toasts

No summary provided by upstream source.

Repository SourceNeeds Review
General

image-gen

Generate AI images from text prompts. Triggers on: "生成图片", "画一张", "AI图", "generate image", "配图", "create picture", "draw", "visualize", "generate an image".

Archived SourceRecently Updated
General

explainer

Create explainer videos with narration and AI-generated visuals. Triggers on: "解说视频", "explainer video", "explain this as a video", "tutorial video", "introduce X (video)", "解释一下XX(视频形式)".

Archived SourceRecently Updated