GET /api/transactions

List transactions

Returns the authenticated user's transactions, ordered by transaction_date descending, paginated 50 per page. Each row is eager-loaded with its account, toAccount, and category.

Response

200 OK
{
  "current_page": 1,
  "data": [
    {
      "id": 42,
      "user_id": 1,
      "account_id": 1,
      "to_account_id": null,
      "category_id": 2,
      "type": "expense",
      "amount": "25.50",
      "description": "Lunch with team",
      "reference": null,
      "transaction_date": "2026-06-03",
      "is_synced": true,
      "created_at": "2026-06-03T12:00:00Z",
      "updated_at": "2026-06-03T12:00:00Z",
      "account": { "id": 1, "name": "GTBank Checking", "type": "bank" },
      "to_account": null,
      "category": { "id": 2, "name": "Groceries", "type": "expense" }
    }
  ],
  "per_page": 50,
  "total": 1,
  "last_page": 1
}
401 Unauthorized
{ "message": "Unauthenticated." }
POST /api/transactions

Create a transaction

Records a new income, expense, or transfer. The user must have at least one account before creating a transaction.

Request body

NameTypeRequiredDescription
account_id integer Required ID of the account the transaction is recorded against.
to_account_id integer Optional Destination account for transfer transactions.
type string Required One of: income, expense, transfer.
category_id integer Optional Category ID. Required for income/expense, optional for transfer.
amount number Required Transaction amount. Always positive.
description string Optional Short description. Max 255 characters.
reference string Optional External reference (e.g. bank transaction ID). Max 255 characters.
transaction_date date Required Date the transaction occurred. YYYY-MM-DD.
force boolean Optional Set to true to skip the duplicate-detection check.

Request body example

REQUEST
{
  "account_id": 1,
  "category_id": 2,
  "type": "expense",
  "amount": 25.50,
  "description": "Lunch with team",
  "transaction_date": "2026-06-03"
}

Responses

201 Created
{
  "id": 42,
  "user_id": 1,
  "account_id": 1,
  "to_account_id": null,
  "category_id": 2,
  "type": "expense",
  "amount": "25.50",
  "description": "Lunch with team",
  "reference": null,
  "transaction_date": "2026-06-03",
  "is_synced": true,
  "created_at": "2026-06-03T12:00:00Z",
  "updated_at": "2026-06-03T12:00:00Z"
}
403 Forbidden
{ "message": "You must create at least one account before adding transactions." }
409 Conflict
{
  "message": "Potential duplicate detected.",
  "is_duplicate": true
}
422 Unprocessable Entity
{
  "message": "The given data was invalid.",
  "errors": {
    "type": ["The selected type is invalid."]
  }
}
POST /api/transactions/sync requires verified email

Bulk sync (offline)

Accepts a batch of transactions recorded offline and dispatches them to a background queue job (App\Jobs\ProcessSync) for processing. Requires a verified email — the batch-write surface is gated by the verified middleware so we have a way to reach the user if the import misbehaves.

Request body

NameTypeRequiredDescription
transactions array Required Array of transaction objects. Each must include account_id, type, amount, and transaction_date.

Request body example

REQUEST
{
  "transactions": [
    {
      "account_id": 1,
      "type": "expense",
      "amount": 12.00,
      "description": "Coffee",
      "transaction_date": "2026-06-02"
    },
    {
      "account_id": 1,
      "type": "expense",
      "amount": 4.50,
      "description": "Bus fare",
      "transaction_date": "2026-06-02"
    }
  ]
}

Responses

200 OK
{ "message": "Sync process started in the background." }
403 Forbidden (email not verified)
{
  "message": "Your email address is not verified.",
  "requires_verified_email": true
}
GET /api/transactions/{id}

Retrieve a transaction

Returns a single transaction with its account, toAccount, and category relations loaded.

PUT /api/transactions/{id}

Update a transaction

Updates one or more fields of an existing transaction. All fields are optional — only the fields you send are updated.

Request body

NameTypeRequiredDescription
account_idintegerOptionalNew source account.
to_account_idintegerOptionalNew destination account for transfers.
category_idintegerOptionalNew category.
typestringOptionalOne of: income, expense, transfer.
amountnumberOptionalNew amount.
descriptionstringOptionalNew description. Max 255 characters.
referencestringOptionalNew reference. Max 255 characters.
transaction_datedateOptionalNew date. YYYY-MM-DD.
DELETE /api/transactions/{id}

Delete a transaction

Permanently removes a transaction and recalculates the affected account balances.

Response

204 No Content
HTTP/1.1 204 No Content

© 2026 Pasona Finance Tracker API. All rights reserved.

API version: v1