> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blnkfinance.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Practice Example

> Hands-on tutorial on performing reconciliation with Blnk Core.

export const CtaCallout = props => {
  const {title, buttonLabel, href, trackingEvent, buttonTarget, rel = "noopener noreferrer", children} = props;
  const handleCtaClick = () => {
    if (typeof window === "undefined" || !trackingEvent) {
      return;
    }
    try {
      window.dispatchEvent(new CustomEvent("blnk:docs-cta", {
        detail: {
          name: trackingEvent,
          href
        }
      }));
    } catch {}
    try {
      window.posthog?.capture?.(trackingEvent, {
        href
      });
    } catch {}
    const gaPayload = {
      cta_href: href
    };
    try {
      window.gtag?.("event", trackingEvent, gaPayload);
    } catch {}
    try {
      window.dataLayer = window.dataLayer || [];
      window.dataLayer.push({
        event: trackingEvent,
        ...gaPayload
      });
    } catch {}
  };
  const isExternal = typeof href === "string" && (/^https?:\/\//i).test(href);
  const target = buttonTarget ?? (isExternal ? "_blank" : undefined);
  const linkRel = isExternal ? rel : undefined;
  return <section className="cta-callout not-prose relative my-8 w-full min-w-0 overflow-hidden rounded-xl border border-zinc-200 p-5 dark:border-white/10">
      <div className="cta-callout-noise" aria-hidden="true" />
      <div className="cta-callout-layout">
        {title ? <div className="cta-callout-title-row">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 28" width="14" height="14" className="cta-callout-icon shrink-0 text-zinc-800 dark:text-zinc-200" aria-hidden="true">
              <g fill="none" fillRule="nonzero">
                <path d="M28 0v28H0V0h28ZM14.691833333333335 27.134333333333334l-0.012833333333333334 0.0023333333333333335 -0.08283333333333333 0.04083333333333334 -0.023333333333333334 0.004666666666666667 -0.016333333333333335 -0.004666666666666667 -0.08283333333333333 -0.04083333333333334c-0.011666666666666667 -0.004666666666666667 -0.022166666666666668 -0.0011666666666666668 -0.028000000000000004 0.005833333333333334l-0.004666666666666667 0.011666666666666667 -0.019833333333333335 0.49933333333333335 0.005833333333333334 0.023333333333333334 0.011666666666666667 0.015166666666666667 0.12133333333333333 0.08633333333333333 0.0175 0.004666666666666667 0.014000000000000002 -0.004666666666666667 0.12133333333333333 -0.08633333333333333 0.014000000000000002 -0.018666666666666668 0.004666666666666667 -0.019833333333333335 -0.019833333333333335 -0.4981666666666667c-0.0023333333333333335 -0.011666666666666667 -0.0105 -0.019833333333333335 -0.019833333333333335 -0.021Zm0.3091666666666667 -0.13183333333333336 -0.015166666666666667 0.0023333333333333335 -0.21583333333333335 0.1085 -0.011666666666666667 0.011666666666666667 -0.0035000000000000005 0.012833333333333334 0.021 0.5016666666666667 0.005833333333333334 0.014000000000000002 0.009333333333333334 0.008166666666666668 0.23450000000000004 0.1085c0.014000000000000002 0.004666666666666667 0.026833333333333334 0 0.03383333333333334 -0.009333333333333334l0.004666666666666667 -0.016333333333333335 -0.03966666666666667 -0.7163333333333334c-0.0035000000000000005 -0.014000000000000002 -0.011666666666666667 -0.023333333333333334 -0.023333333333333334 -0.025666666666666667Zm-0.8341666666666667 0.0023333333333333335a0.026833333333333334 0.026833333333334334 0 0 0 -0.0315 0.007000000000000001l-0.007000000000000001 0.016333333333333335 -0.03966666666666667 0.7163333333333334c0 0.014000000000000002 0.008166666666666668 0.023333333333333334 0.019833333333333335 0.028000000000000004l0.0175 -0.0023333333333333335 0.23450000000000004 -0.1085 0.011666666666666667 -0.009333333333333334 0.004666666666666667 -0.012833333333333334 0.019833333333333335 -0.5016666666666667 -0.0035000000000000005 -0.014000000000000002 -0.011666666666666667 -0.011666666666666667 -0.21466666666666667 -0.10733333333333334Z" strokeWidth="1.1667" />
                <path fill="currentColor" d="M14 2.916666666666667A1.75 1.75 0 0 1 15.750000000000002 4.666666666666667v6.302333333333334L21.207666666666668 7.816666666666667a1.75 1.75 0 0 1 1.75 3.031L17.5 14l5.457666666666667 3.151166666666667a1.75 1.75 0 0 1 -1.75 3.031l-5.457666666666667 -3.1500000000000004V23.333333333333336a1.75 1.75 0 0 1 -3.5 0v-6.302333333333334L6.792333333333334 20.183333333333337a1.75 1.75 0 1 1 -1.75 -3.031L10.5 14 5.042333333333334 10.848833333333333a1.75 1.75 0 0 1 1.75 -3.031l5.457666666666667 3.1500000000000004V4.666666666666667A1.75 1.75 0 0 1 14 2.916666666666667Z" strokeWidth="1.1667" />
              </g>
            </svg>
            <p className="cta-callout-title min-w-0 font-semibold text-zinc-800 dark:text-zinc-200">
              {title}
            </p>
          </div> : null}
        <div className={`cta-callout-body text-sm leading-normal text-zinc-800 dark:text-zinc-200${title ? " cta-callout-body--indented" : ""}`}>
          {children}
        </div>
        <a href={href} target={target} rel={linkRel} onClick={handleCtaClick} data-docs-cta={trackingEvent || undefined} className="cta-callout-button inline-flex items-center justify-center gap-1 rounded-full bg-white px-3 py-1.5 text-sm font-semibold transition hover:bg-zinc-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white/50 dark:bg-white dark:hover:bg-zinc-200">
          {buttonLabel}
          <span className="cta-callout-button-arrow" aria-hidden="true">
            →
          </span>
        </a>
      </div>
    </section>;
};

In this guide, you'll learn how to perform a simple one-to-one reconciliation workflow with Blnk. This includes:

1. Preparing and uploading our data.
2. Creating our matching rules.
3. Running our reconciliation process.
4. Review the reconciliation results.

For this example, we'll use Postman or cURL to send our API requests. You can also refer to the [API reference](/reference/start-reconciliation) for details on the available endpoints.

***

## Prerequisites

Before starting, ensure you have:

1. A running Blnk server instance (e.g. at `http://localhost:5001`). Version 0.10.0 or later.

***

## Recording sample transactions

First, import the following sample transactions using the [Bulk Transactions](/transactions/bulk-transactions) feature:

<CodeGroup>
  ```bash cURL wrap expandable theme={"system"}
  curl -X POST "http://localhost:5001/transactions/bulk" \
    -H "X-blnk-key: <api-key>" \
    -H "Content-Type: application/json" \
    -d '{
      "atomic": true,
      "inflight": false,
      "run_async": false,
      "transactions": [
        {
          "amount": 152.75,
          "precision": 100,
          "reference": "txn_001",
          "description": "Invoice settlement",
          "currency": "USD",
          "source": "@WorldA",
          "allow_overdraft": true,
          "destination": "@WorldB"
        },
      {
        "amount": 329.40,
        "precision": 100,
        "reference": "txn_002",
        "description": "Refund processing",
        "currency": "USD",
        "source": "@WorldB",
        "allow_overdraft": true,
        "destination": "@WorldA"
      },
      {
        "amount": 87.15,
        "precision": 100,
        "reference": "txn_003",
        "description": "Service charge",
        "currency": "USD",
        "source": "@WorldA",
        "allow_overdraft": true,
        "destination": "@WorldB"
      },
      {
        "amount": 413.60,
        "precision": 100,
        "reference": "txn_004",
        "description": "Payment for goods",
        "currency": "USD",
        "source": "@WorldB",
        "allow_overdraft": true,
        "destination": "@WorldA"
      },
      {
        "amount": 276.89,
        "precision": 100,
        "reference": "txn_005",
        "description": "Subscription fee",
        "currency": "USD",
        "source": "@WorldA",
        "allow_overdraft": true,
        "destination": "@WorldB"
      },
      {
        "amount": 199.99,
        "precision": 100,
        "reference": "txn_006",
        "description": "Expense reimbursement",
        "currency": "USD",
        "source": "@WorldB",
        "allow_overdraft": true,
        "destination": "@WorldA"
      },
      {
        "amount": 540.25,
        "precision": 100,
        "reference": "txn_007",
        "description": "Project funding",
        "currency": "USD",
        "source": "@WorldA",
        "allow_overdraft": true,
        "destination": "@WorldB"
      },
      {
        "amount": 135.70,
        "precision": 100,
        "reference": "txn_008",
        "description": "Loan repayment",
        "currency": "USD",
        "source": "@WorldB",
        "allow_overdraft": true,
        "destination": "@WorldA"
      },
      {
        "amount": 92.80,
        "precision": 100,
        "reference": "txn_009",
        "description": "Freelance payment",
        "currency": "USD",
        "source": "@WorldA",
        "allow_overdraft": true,
        "destination": "@WorldB"
      },
      {
        "amount": 480.55,
        "precision": 100,
        "reference": "txn_010",
        "description": "Revenue share",
        "currency": "USD",
        "source": "@WorldB",
        "allow_overdraft": true,
        "destination": "@WorldA"
      }
    ]
  }'
  ```

  ```typescript TypeScript wrap expandable theme={"system"}
  const response = await blnk.Transactions.createBulk({
    atomic: true,
    inflight: false,
    run_async: false,
    transactions: [
      {
        amount: 152.75,
        precision: 100,
        reference: 'txn_001',
        description: 'Invoice settlement',
        currency: 'USD',
        source: '@WorldA',
        allow_overdraft: true,
        destination: '@WorldB',
      },
      {
        amount: 329.4,
        precision: 100,
        reference: 'txn_002',
        description: 'Refund processing',
        currency: 'USD',
        source: '@WorldB',
        allow_overdraft: true,
        destination: '@WorldA',
      },
      {
        amount: 87.15,
        precision: 100,
        reference: 'txn_003',
        description: 'Service charge',
        currency: 'USD',
        source: '@WorldA',
        allow_overdraft: true,
        destination: '@WorldB',
      },
      {
        amount: 413.6,
        precision: 100,
        reference: 'txn_004',
        description: 'Payment for goods',
        currency: 'USD',
        source: '@WorldB',
        allow_overdraft: true,
        destination: '@WorldA',
      },
      {
        amount: 276.89,
        precision: 100,
        reference: 'txn_005',
        description: 'Subscription fee',
        currency: 'USD',
        source: '@WorldA',
        allow_overdraft: true,
        destination: '@WorldB',
      },
      {
        amount: 199.99,
        precision: 100,
        reference: 'txn_006',
        description: 'Expense reimbursement',
        currency: 'USD',
        source: '@WorldB',
        allow_overdraft: true,
        destination: '@WorldA',
      },
      {
        amount: 540.25,
        precision: 100,
        reference: 'txn_007',
        description: 'Project funding',
        currency: 'USD',
        source: '@WorldA',
        allow_overdraft: true,
        destination: '@WorldB',
      },
      {
        amount: 135.7,
        precision: 100,
        reference: 'txn_008',
        description: 'Loan repayment',
        currency: 'USD',
        source: '@WorldB',
        allow_overdraft: true,
        destination: '@WorldA',
      },
      {
        amount: 92.8,
        precision: 100,
        reference: 'txn_009',
        description: 'Freelance payment',
        currency: 'USD',
        source: '@WorldA',
        allow_overdraft: true,
        destination: '@WorldB',
      },
      {
        amount: 480.55,
        precision: 100,
        reference: 'txn_010',
        description: 'Revenue share',
        currency: 'USD',
        source: '@WorldB',
        allow_overdraft: true,
        destination: '@WorldA',
      },
    ],
  });
  ```
</CodeGroup>

```json Response theme={"system"}
{
  "batch_id": "bulk_4192d961-5b0e-46ca-bf2f-9386763057f8",
  "status": "applied",
  "transaction_count": 10
}
```

***

## Preparing the external data

Next, download the sample CSV file provided below.

This file will act as our external data source and has already been formatted to meet Blnk's specifications. See [External Data Preparation](/reconciliations/external-data) for more details.

<Card title="External data source" icon="file-spreadsheet" href="https://github.com/blnkfinance/blnk-docs/blob/main/resources/recon-example-external-source.csv">
  Sample CSV for reconciliation practice.
</Card>

***

## Uploading the data

Upload your CSV file with the [Upload Data](/reference/upload-data) endpoint:

<CodeGroup>
  ```bash cURL wrap theme={"system"}
  curl --location 'https://YOUR_BLNK_INSTANCE_URL/reconciliation/upload' \
  --form 'file=@recon-example-external-source.csv' \
  --form 'source=Stripe'
  ```

  ```typescript TypeScript wrap theme={"system"}
  const response = await blnk.Reconciliation.upload(
    'recon-example-external-source.csv',
    'Stripe',
  );
  ```

  ```go Go wrap theme={"system"}
  file, _ := os.Open("recon-example-external-source.csv")
  result, resp, err := client.Reconciliation.Upload("Stripe", file, file.Name())
  ```
</CodeGroup>

```json Response theme={"system"}
{
  "record_count": 10,
  "source": "Stripe",
  "upload_id": "upload_0cd4a87d-544c-4b7e-9232-f36e79631c32"
}
```

<Tip>Save the `upload_id`. You’ll need it to start the reconciliation.</Tip>

***

## Setting our matching rules

We’ll define rules to match internal and external transactions. For this example, we want:

1. **Amount Match**: Exact amount match

2. **Currency Match**: Exact matches for both fields.

3. **Reference Match**: Exact matches for both references

All rules must be true for successful matching. Create the rule with this request:

<CodeGroup>
  ```bash cURL wrap expandable theme={"system"}
  curl -X POST "http://localhost:5001/reconciliation/matching-rules" \
    -H "X-blnk-key: <api-key>" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Basic matcher",
      "description": "Matches transactions by amount and reference",
      "criteria": [
          {
              "field": "amount",
              "operator": "equals"
          },
          {
              "field": "currency",
              "operator": "equals"
          },
          {
              "field": "reference",
              "operator": "equals"
          }
      ]
    }'
  ```

  ```typescript TypeScript wrap expandable theme={"system"}
  const response = await blnk.Reconciliation.createMatchingRule({
    name: 'Basic matcher',
    description: 'Matches transactions by amount and reference',
    criteria: [
      {
        field: 'amount',
        operator: 'equals',
      },
      {
        field: 'currency',
        operator: 'equals',
      },
      {
        field: 'reference',
        operator: 'equals',
      },
    ],
  });
  ```

  ```go Go wrap expandable theme={"system"}
  rule, resp, err := client.Reconciliation.CreateMatchingRule(blnkgo.Matcher{
    Name:        "Basic matcher",
    Description: "Matches transactions by amount and reference",
    Criteria: []blnkgo.Criteria{
      {
        Field:    blnkgo.CriteriaFieldAmount,
        Operator: blnkgo.ReconciliationOperatorEquals,
      },
      {
        Field:    blnkgo.CriteriaFieldCurrency,
        Operator: blnkgo.ReconciliationOperatorEquals,
      },
      {
        Field:    blnkgo.CriteriaFieldReference,
        Operator: blnkgo.ReconciliationOperatorEquals,
      },
    },
  })
  ```
</CodeGroup>

```json Response expandable theme={"system"}
{
    "rule_id": "rule_3d5ae6d4-6722-40c5-ac4b-0bd66ab7d363",
    "created_at": "2025-03-17T08:31:24.97610651Z",
    "updated_at": "2025-03-17T08:31:24.976106635Z",
    "name": "Basic matcher",
    "description": "Matches transactions by amount and reference",
    "criteria": [
        {
            "field": "amount",
            "operator": "equals",
            "value": "",
            "pattern": "",
            "allowable_drift": 0
        },
        {
            "field": "currency",
            "operator": "equals",
            "value": "",
            "pattern": "",
            "allowable_drift": 0
        },
        {
            "field": "reference",
            "operator": "equals",
            "value": "",
            "pattern": "",
            "allowable_drift": 0
        }
    ]
}
```

<Tip>Save the `rule_id` for the reconciliation step.</Tip>

***

## Run reconciliation

With the external data uploaded and our matching rules configured, we’re ready to run our first reconciliation.

In this example, we’ll use the [Batch Reconciliation](/reconciliations/overview#option-1-batch-reconciliation) option and apply a `one_to_one` strategy to ensure precise matching.

See [Reconciliation Strategies](/reconciliations/strategies) for details.

Send this request to start the reconciliation:

<CodeGroup>
  ```bash cURL wrap theme={"system"}
  curl -X POST "http://localhost:5001/reconciliation/start" \
    -H "X-blnk-key: <api-key>" \
    -H "Content-Type: application/json" \
    -d '{
      "upload_id": "upload_0cd4a87d-544c-4b7e-9232-f36e79631c32",
      "strategy": "one_to_one",
      "matching_rule_ids": [
          "rule_3d5ae6d4-6722-40c5-ac4b-0bd66ab7d363"
      ]
    }'
  ```

  ```typescript TypeScript wrap theme={"system"}
  const response = await blnk.Reconciliation.run({
    upload_id: 'upload_0cd4a87d-544c-4b7e-9232-f36e79631c32',
    strategy: 'one_to_one',
    matching_rule_ids: [
      'rule_3d5ae6d4-6722-40c5-ac4b-0bd66ab7d363',
    ],
  });
  ```

  ```go Go wrap theme={"system"}
  result, resp, err := client.Reconciliation.Run(blnkgo.RunReconData{
    UploadID: "upload_0cd4a87d-544c-4b7e-9232-f36e79631c32",
    Strategy: blnkgo.ReconciliationStrategyOneToOne,
    MatchingRuleIDs: []string{
      "rule_3d5ae6d4-6722-40c5-ac4b-0bd66ab7d363",
    },
  })
  ```
</CodeGroup>

```json Response theme={"system"}
{
    "reconciliation_id": "recon_f1df3e68-fd8d-4566-8670-891c3c1e7d58"
}
```

***

## View reconciliation results

Finally, you can view the status of your reconciliation with the following endpoint:

<CodeGroup>
  ```bash cURL wrap theme={"system"}
  curl -X GET "https://YOUR_BLNK_INSTANCE_URL/reconciliation/{reconciliation_id}" \
    -H "X-blnk-key: <api-key>"
  ```
</CodeGroup>

```json Response theme={"system"}
{
  "reconciliation_id": "recon_f1df3e68-fd8d-4566-8670-891c3c1e7d58",
  "upload_id": "upload_0cd4a87d-544c-4b7e-9232-f36e79631c32",
  "status": "completed",
  "matched_transactions": 2,
  "unmatched_transactions": 8,
  "is_dry_run": false,
  "started_at": "2025-03-17T08:32:24.005476Z",
  "completed_at": "2025-03-17T08:32:24.062136Z"
}
```

| Field                    | Description                             |
| :----------------------- | :-------------------------------------- |
| `matched_transactions`   | Number of external records matched.     |
| `unmatched_transactions` | Number of external records not matched. |

***

## Error handling

1. **401 Unauthorized**: Ensure your API key is correct and included in the `Authorization` header.

2. **400 Bad Request**: Check your request body or file format. For uploads, ensure the CSV matches Blnk’s specifications.

3. **404 Not Found**: Verify the endpoint URL (e.g., `/reconciliation/upload` for uploads, `/reconciliation/start` for reconciliation).

***

## Need help?

We are very happy to help you make the most of Blnk, regardless of whether it is your first time or you are switching from another tool.

To ask questions or discuss issues, please [contact us](mailto:support@blnkfinance.com) or [join our Discord community](https://discord.gg/7WNv94zPpx).

<CtaCallout title="Connect your ledger to Blnk Cloud" href="https://cloud.blnkfinance.com/auth/sign-up?utm_source=blnk_docs&utm_medium=documentation&utm_campaign=need-help" buttonLabel="Open Blnk Cloud" trackingEvent="clicked_cloud_signup">
  Sign up and manage your ledger with our back-office dashboard. You can invite teammates to collaborate and manage your ledger operations directly from the dashboard.
</CtaCallout>
