View as Markdown

llms.txt

No such blueprint

This instance publishes no blueprint at that address. The catalog lists every one it does publish.

Back to the blueprints

Blueprints Testing scenarios

Simulate a card decline

Send a card sale the sandbox always refuses, and handle the refusal where it actually arrives: in the response body, not as a transport error.

Signed in, you can run this blueprint against your own sandbox merchant one call at a time, with the values from each call threaded into the next. Sign in to run it.

2 steps, 1 API callPaymentsTransactions

Samples use {{API_KEY}} for your API key and {{BASE_URL}} for this instance's API address. Anything else in double braces is a value an earlier step gave you.

Reproduce it in the sandbox

1. Send the sale at the declining amount

API call

POST /api/transactions

The cents of the amount pick the outcome, and the rest of the amount is ignored, so this is the same sale request as any other with one number changed.

Reference for this operation

Values this step gives you

    cURL

    curl -X POST "{{BASE_URL}}/api/transactions" \
      -H "api-key: {{API_KEY}}" \
      -H "Content-Type: application/json" \
      -d '{
        "transactionType": "Sale",
        "cardData": {
          "cardNumber": "4111111111111111",
          "nameOnCard": "Jane Doe",
          "expirationMonth": 12,
          "expirationYear": 2030,
          "cvv": 123
        },
        "invoiceData": {
          "amounts": { "base": 10.01, "total": 10.01 }
        }
      }'
    .NET

    using var http = new HttpClient { BaseAddress = new Uri("{{BASE_URL}}") };
    http.DefaultRequestHeaders.Add("api-key", "{{API_KEY}}");
    
    var response = await http.PostAsJsonAsync("/api/transactions", new
    {
        transactionType = "Sale",
        cardData = new
        {
            cardNumber = "4111111111111111",
            nameOnCard = "Jane Doe",
            expirationMonth = 12,
            expirationYear = 2030,
            cvv = 123
        },
        invoiceData = new
        {
            amounts = new { @base = 10.01m, total = 10.01m }
        }
    });
    
    var result = await response.Content.ReadFromJsonAsync<JsonElement>();
    var resultCode = result.GetProperty("responseData").GetProperty("resultCode").GetString();

    2. Read the outcome off the response

    On your side

    The sandbox answers with the result code "Decline" and the message "AUTH DECLINED" in the response body. The platform files that result under the "Declined" outcome. The response carries host error 200. The refusal arrives on a successful HTTP response, because the request itself worked: a refused card is a business outcome, not a transport failure. An integration that decides on the status code alone reads this as a completed payment, which is the mistake this scenario exists to find.

    Reference for this operation

    Values this step gives you

      What this step answers with

      Abridged to the properties this step depends on. A real response carries more.

      HTTP 200

      {
        "id": "9f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
        "merchantId": "3a7b1c9d-2e4f-4a6b-8c8d-9e0f1a2b3c4d",
        "resultCode": "Decline",
        "responseData": {
          "resultCode": "Decline",
          "resultMessage": "AUTH DECLINED"
        }
      }

      Run the whole flow as one script

      Every step above in one script you can copy and run. Replace {{API_KEY}} with your own API key and {{BASE_URL}} with this instance's API address, and set any value the script asks you for at the top. A step that happens outside the API stays a comment.

      Code sample language

      brew install jq

      cURL

      #!/usr/bin/env bash
      # Simulate a card decline
      #
      # Send a card sale the sandbox always refuses, and handle the refusal where it actually arrives: in
      # the response body, not as a transport error.
      #
      # Every API call in this blueprint, in order. Each value a call returns is passed to the calls after
      # it. A step that happens outside the API is a comment, and any failed call stops the script.
      
      set -euo pipefail
      
      BASE_URL="{{BASE_URL}}"
      API_KEY="{{API_KEY}}"
      
      # Sends one request and prints the response body. A failed call prints the API's answer and stops
      # the script.
      call() {
        local method="$1" path="$2" body="${3:-}" out
        local args=(-sS --fail-with-body -X "$method" "$BASE_URL$path" -H "api-key: $API_KEY")
        if [ -n "$body" ]; then
          args+=(-H "Content-Type: application/json" -d "$body")
        fi
        if ! out=$(curl "${args[@]}"); then
          printf '%s\n' "$out" >&2
          return 1
        fi
        printf '%s' "$out"
      }
      
      # Phase 1: Reproduce it in the sandbox
      
      # Step 1: Send the sale at the declining amount
      call POST "/api/transactions" '{
        "transactionType": "Sale",
        "cardData": {
          "cardNumber": "4111111111111111",
          "nameOnCard": "Jane Doe",
          "expirationMonth": 12,
          "expirationYear": 2030,
          "cvv": 123
        },
        "invoiceData": {
          "amounts": { "base": 10.01, "total": 10.01 }
        }
      }' > /dev/null
      
      # Step 2: Read the outcome off the response
      # The sandbox answers with the result code "Decline" and the message "AUTH DECLINED" in the response
      # body. The platform files that result under the "Declined" outcome. The response carries host error
      # 200. The refusal arrives on a successful HTTP response, because the request itself worked: a
      # refused card is a business outcome, not a transport failure. An integration that decides on the
      # status code alone reads this as a completed payment, which is the mistake this scenario exists to
      # find.
      

      PowerShell

      # Simulate a card decline
      #
      # Send a card sale the sandbox always refuses, and handle the refusal where it actually arrives: in
      # the response body, not as a transport error.
      #
      # Every API call in this blueprint, in order. Each value a call returns is passed to the calls after
      # it. A step that happens outside the API is a comment, and any failed call stops the script.
      
      $ErrorActionPreference = 'Stop'
      
      $baseUrl = '{{BASE_URL}}'
      $apiKey = '{{API_KEY}}'
      
      # Sends one request and returns the parsed response body. A failed call stops the script.
      function Invoke-BlueprintCall([string] $Method, [string] $Path, [string] $Body) {
          $arguments = @{
              Method  = $Method
              Uri     = $baseUrl + $Path
              Headers = @{ 'api-key' = $apiKey }
          }
          if ($Body) {
              $arguments.ContentType = 'application/json'
              $arguments.Body = [System.Text.Encoding]::UTF8.GetBytes($Body)
          }
          Invoke-RestMethod @arguments
      }
      
      # Phase 1: Reproduce it in the sandbox
      
      # Step 1: Send the sale at the declining amount
      $body = @'
      {
        "transactionType": "Sale",
        "cardData": {
          "cardNumber": "4111111111111111",
          "nameOnCard": "Jane Doe",
          "expirationMonth": 12,
          "expirationYear": 2030,
          "cvv": 123
        },
        "invoiceData": {
          "amounts": { "base": 10.01, "total": 10.01 }
        }
      }
      '@
      $null = Invoke-BlueprintCall -Method 'POST' -Path '/api/transactions' -Body $body
      
      # Step 2: Read the outcome off the response
      # The sandbox answers with the result code "Decline" and the message "AUTH DECLINED" in the response
      # body. The platform files that result under the "Declined" outcome. The response carries host error
      # 200. The refusal arrives on a successful HTTP response, because the request itself worked: a
      # refused card is a business outcome, not a transport failure. An integration that decides on the
      # status code alone reads this as a completed payment, which is the mistake this scenario exists to
      # find.
      

      TypeScript

      // Simulate a card decline
      //
      // Send a card sale the sandbox always refuses, and handle the refusal where it actually arrives: in
      // the response body, not as a transport error.
      //
      // Every API call in this blueprint, in order. Each value a call returns is passed to the calls
      // after it. A step that happens outside the API is a comment, and any failed call stops the script.
      
      export {};
      
      const baseUrl = '{{BASE_URL}}';
      const apiKey = '{{API_KEY}}';
      
      // Sends one request and returns the parsed response body. A failed call throws.
      async function call(method: string, path: string, body?: unknown): Promise<any> {
        const headers: Record<string, string> = { 'api-key': apiKey };
        if (body !== undefined) {
          headers['Content-Type'] = 'application/json';
        }
      
        const response = await fetch(baseUrl + path, {
          method,
          headers,
          body: body === undefined ? undefined : JSON.stringify(body),
        });
      
        const text = await response.text();
        if (!response.ok) {
          throw new Error(`${method} ${path} answered ${response.status}: ${text}`);
        }
      
        return text ? JSON.parse(text) : null;
      }
      
      // Phase 1: Reproduce it in the sandbox
      
      // Step 1: Send the sale at the declining amount
      await call('POST', '/api/transactions', {
        "transactionType": "Sale",
        "cardData": {
          "cardNumber": "4111111111111111",
          "nameOnCard": "Jane Doe",
          "expirationMonth": 12,
          "expirationYear": 2030,
          "cvv": 123
        },
        "invoiceData": {
          "amounts": { "base": 10.01, "total": 10.01 }
        }
      });
      
      // Step 2: Read the outcome off the response
      // The sandbox answers with the result code "Decline" and the message "AUTH DECLINED" in the
      // response body. The platform files that result under the "Declined" outcome. The response carries
      // host error 200. The refusal arrives on a successful HTTP response, because the request itself
      // worked: a refused card is a business outcome, not a transport failure. An integration that
      // decides on the status code alone reads this as a completed payment, which is the mistake this
      // scenario exists to find.
      

      C#

      // Simulate a card decline
      //
      // Send a card sale the sandbox always refuses, and handle the refusal where it actually arrives: in
      // the response body, not as a transport error.
      //
      // Every API call in this blueprint, in order. Each value a call returns is passed to the calls
      // after it. A step that happens outside the API is a comment, and any failed call stops the script.
      
      using System.Text;
      using System.Text.Json;
      
      var baseUrl = "{{BASE_URL}}";
      var apiKey = "{{API_KEY}}";
      
      using var http = new HttpClient();
      http.DefaultRequestHeaders.Add("api-key", apiKey);
      
      // Sends one request and returns the parsed response body. A failed call throws.
      async Task<JsonElement> CallAsync(string method, string path, string? body = null)
      {
          using var request = new HttpRequestMessage(new HttpMethod(method), baseUrl + path);
          if (body is not null)
          {
              request.Content = new StringContent(body, Encoding.UTF8, "application/json");
          }
      
          using var response = await http.SendAsync(request);
          var json = await response.Content.ReadAsStringAsync();
          if (!response.IsSuccessStatusCode)
          {
              throw new HttpRequestException($"{method} {path} answered {(int)response.StatusCode}: {json}");
          }
      
          return json.Length == 0 ? default : JsonSerializer.Deserialize<JsonElement>(json);
      }
      
      // Phase 1: Reproduce it in the sandbox
      
      // Step 1: Send the sale at the declining amount
      await CallAsync("POST", "/api/transactions", """
          {
            "transactionType": "Sale",
            "cardData": {
              "cardNumber": "4111111111111111",
              "nameOnCard": "Jane Doe",
              "expirationMonth": 12,
              "expirationYear": 2030,
              "cvv": 123
            },
            "invoiceData": {
              "amounts": { "base": 10.01, "total": 10.01 }
            }
          }
          """);
      
      // Step 2: Read the outcome off the response
      // The sandbox answers with the result code "Decline" and the message "AUTH DECLINED" in the
      // response body. The platform files that result under the "Declined" outcome. The response carries
      // host error 200. The refusal arrives on a successful HTTP response, because the request itself
      // worked: a refused card is a business outcome, not a transport failure. An integration that
      // decides on the status code alone reads this as a completed payment, which is the mistake this
      // scenario exists to find.
      

      pip install requests

      Python

      # Simulate a card decline
      #
      # Send a card sale the sandbox always refuses, and handle the refusal where it actually arrives: in
      # the response body, not as a transport error.
      #
      # Every API call in this blueprint, in order. Each value a call returns is passed to the calls after
      # it. A step that happens outside the API is a comment, and any failed call stops the script.
      
      import requests
      
      BASE_URL = "{{BASE_URL}}"
      API_KEY = "{{API_KEY}}"
      
      
      # Sends one request and returns the parsed response body. A failed call raises.
      def call(method, path, body=None):
          response = requests.request(
              method,
              BASE_URL + path,
              headers={"api-key": API_KEY},
              json=body,
          )
          response.raise_for_status()
          return response.json() if response.content else None
      
      
      # Phase 1: Reproduce it in the sandbox
      
      # Step 1: Send the sale at the declining amount
      call("POST", "/api/transactions", {
        "transactionType": "Sale",
        "cardData": {
          "cardNumber": "4111111111111111",
          "nameOnCard": "Jane Doe",
          "expirationMonth": 12,
          "expirationYear": 2030,
          "cvv": 123
        },
        "invoiceData": {
          "amounts": { "base": 10.01, "total": 10.01 }
        }
      })
      
      # Step 2: Read the outcome off the response
      # The sandbox answers with the result code "Decline" and the message "AUTH DECLINED" in the response
      # body. The platform files that result under the "Declined" outcome. The response carries host error
      # 200. The refusal arrives on a successful HTTP response, because the request itself worked: a
      # refused card is a business outcome, not a transport failure. An integration that decides on the
      # status code alone reads this as a completed payment, which is the mistake this scenario exists to
      # find.
      

      Reconnecting to the server

      Could not reconnect

      This session has ended

      Attempt 1

      Your work on this page is still here. Retrying keeps it; reloading starts the page again.

      The server no longer holds this page's state, so it has to be loaded again.