# Transactions

## What is a Trustap transaction?

A transaction is the central object in the Trustap API.
It represents a single exchange between exactly one buyer and exactly one seller, from the moment it is created until it is completed, cancelled, or refunded.
Almost every action in the Trustap API revolves around a transaction. Rather than creating separate resources for payments, shipping, refunds, or complaints, Trustap records these activities on the transaction itself.

Some properties of the transaction object are mutable. The same transaction ID is returned throughout its lifetime, but additional properties are populated as the transaction progresses. Rather than creating separate payment, shipping, refund, or complaint resources, Trustap records these activities on the transaction itself.

## Transaction lifecycle

A transaction evolves over time.
It begins with a small amount of information and gradually accumulates more data as different actions occur.

For example:

1. You create a transaction with a buyer and seller.
2. The buyer pays.
3. You add shipping information, if applicable.
4. The carrier delivers the item.
5. The complaints period ends.
6. Trustap releases funds to the seller.


Trustap updates the same transaction object throughout this lifecycle instead of creating
new resources. Read our [lifecycle guide](/docs/guides/transactions/transaction-lifecycle) for more details.

## Create a transaction

A transaction requires information about the exchange, including the parties involved and how it is priced. For more information, read our [Users](/docs/guides/transactions/users) and [Fees](/docs/concepts/pricing) guides.

When you create a transaction, you provide the initial details of the exchange, including the buyer, seller, amount, currency, and fees.

Create a transaction
```CURL
curl -i -X POST \
  -u '<API_KEY>:​' \
  https://api.test.trustap.com/v2/transactions \
  -H 'Content-Type: application/json' \
  -d '{
    "amount": 20000,
    "currency": "eur",
    "description": "Trustap socks",
    "fees_buyer": 1050,
    "payment_method": "card",
    "seller_id": "1-22ad0309-d966-440c-8296-9989ff65eebf",
    "buyer_id": "1-a5034d6a-1110-4d33-b6dd-c6ff1b3b2e28"
  }'
```

Response
```JSON
{
	"buyer": {
		"id": "1-a5034d6a-1110-4d33-b6dd-c6ff1b3b2e28",
		"is_guest": true
	},
	"client_id": "5a3d7990-9f1c-4e11-8d67-3da5b160c50a",
	"deadlines": {
		"complaints": null
	},
	"description": "Trustap socks",
	"events": {
		"by_key": {
			"created": "2026-07-30T13:52:38Z",
			"joined": "2026-07-30T13:52:38Z"
		},
		"by_time": [
			{
				"at": "2026-07-30T13:52:38Z",
				"code": "created"
			},
			{
				"at": "2026-07-30T13:52:38Z",
				"code": "joined"
			}
		]
	},
	"funds_release": {
		"refunds": [],
		"released_to_seller": false
	},
	"id": "tx_01kysmrw4xf1h9wcfn8413xdf6",
	"metadata": {},
	"payment_link": "https://actions.stage.trustap.com/transactions/tx_01kysmrw4xf1h9wcfn8413xdf6/pay",
	"pricing": {
		"amount": 20000,
		"amount_extra": 0,
		"currency": "eur",
		"fees": {
			"buyer": 1050,
			"buyer_client": 0,
			"seller": 0,
			"seller_client": 0
		}
	},
	"seller": {
		"id": "1-22ad0309-d966-440c-8296-9989ff65eebf",
		"is_guest": true
	},
	"status": "joined"
}
```

Send the `payment_link` from the response to your buyer so they can complete payment and progress the transaction to the next stage.

You can create a transaction without a `buyer_id`. When your buyer pays for the transaction using the Trustap payment screen, they will be prompted to include their name and email address. This information is automatically added to the transaction object.

Transactions are referenced by their ID. Transactions IDs are globally unique string identifiers that are prefixed with `tx_`. For example, `tx_01kysmrw4xf1h9wcfn8413xdf6`.

## Events

Every transaction includes an events object that records what has happened throughout its lifetime.
The events are exposed in two complementary formats, each optimized for a different use case.

| Property | Best for |
|  --- | --- |
| `events.by_key` | Quickly checking whether a specific event has occurred, and when. |
| `events.by_time` | Viewing the complete chronological history of a transaction, including repeated events and who performed each action. |


### events.by_key

Use `by_key` to look up important transaction milestones directly. Each property
represents an event code. The value shows the timestamp when that event first occurs.
Retrieve repeated event occurrences from the `by_time` property.

This format optimises common integration tasks. Use it to check if a buyer pays, or if a
seller ships, refunds, or cancels a transaction. Instead of searching through an array of
events, you access the event directly.

```JSON by_key sample
"by_key": {
	"created": "2026-07-30T14:03:17Z",
	"joined": "2026-07-30T14:03:17Z"
}
```

```JS Code example to extract by_key data
const transaction = await getTransaction(transactionId);
const by_key = transaction.events?.by_key || {};

// Direct lookup — undefined if the event hasn't happened yet
const createdAt = by_key.created;
const joinedAt = by_key.joined;

if (createdAt) {
  console.log(`Transaction created at ${createdAt}`);
}

if (joinedAt) {
  console.log(`Buyer joined at ${joinedAt}`);
} else {
  console.log("Buyer hasn't joined yet");
}
```

### events.by_time

The `by_time` property logs the complete chronological history of the transaction. Unlike
`by_key`, each entry represents a single event occurrence. This property preserves the
exact order of actions.

Use this format to display an activity timeline or audit the complete history of a
transaction. Because `by_time` is a chronological log, you must search or iterate through
the array to locate a specific event.

```JSON by_time sample
"by_time": [
	{
		"at": "2026-07-30T14:03:17Z",
		"code": "created"
	},
	{
		"at": "2026-07-30T14:03:17Z",
		"code": "joined"
	}
]
```

```JS Code example to extract by_time data
const transaction = await getTransaction(transactionId);
const { by_time = [] } = transaction.events;

// Target date to filter by (YYYY-MM-DD)
const targetDate = "2026-07-30";

// Filter events that occurred on the target date
const eventsOnDate = by_time.filter((event) => event.at.startsWith(targetDate));

if (eventsOnDate.length > 0) {
  console.log(`Found ${eventsOnDate.length} event(s) on ${targetDate}:`);
  eventsOnDate.forEach((event) => {
    console.log(`- [${event.at}] ${event.code}`);
  });
} else {
  console.log(`No events occurred on ${targetDate}`);
}
```

For most integrations, use `events.by_key`. It provides the simplest way to check whether a transaction has reached a specific milestone. Use `events.by_time` when you need the complete transaction history, event ordering, repeated events, or information about who performed an action.