PHPackages                             spiral/writeaway - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. spiral/writeaway

ActiveLibrary[API Development](/categories/api)

spiral/writeaway
================

PHP API server for Writeaway editor

v0.4.0(4y ago)115.1k2[1 issues](https://github.com/spiral/writeaway/issues)[1 PRs](https://github.com/spiral/writeaway/pulls)1MITPHPPHP &gt;=8.0

Since Nov 11Pushed 3y ago5 watchersCompare

[ Source](https://github.com/spiral/writeaway)[ Packagist](https://packagist.org/packages/spiral/writeaway)[ RSS](/packages/spiral-writeaway/feed)WikiDiscussions master Synced today

READMEChangelog (4)Dependencies (8)Versions (6)Used By (1)

PHP API server for Writeaway editor
===================================

[](#php-api-server-for-writeaway-editor)

License:
--------

[](#license)

MIT License (MIT). Please see [`LICENSE`](./LICENSE) for more information. Maintained by [Spiral Scout](https://spiralscout.com).

TODO
----

[](#todo)

- add tests for public services

Usage
-----

[](#usage)

- Register `WriteawayBootloader` in the App

> Note that it must be registered and after `RouterBootloader`.

- Implement `MetaProviderInterface`
- `WriteawayCommandBootloader` can be added if you want to have a reset command.

> Note that it uses `TokenizerBootloader` so it must be registered before `CommandsBootloader`.

- `WriteawayViewsBootloader` can be added if you want use ready views bundle.

API Endpoints:
--------------

[](#api-endpoints)

### List Images

[](#list-images)

**GET** or **POST** `writeaway:images:list` to fetch a full list of available images.

Example response:

```
{
  "status": 200,
  "data": [
    {
      "id": "unique-id",
      "src": "image1.png"
    },
    {
      "id": "unique-id",
      "thumbnailSrc": "image2-th.png",
      "src": "image2.png"
    }
  ]
}
```

Possible image fields:

FieldTypeRequiredDescriptionidstring**Required**Image idsrcstring**Required**Image source URLthumbnailSrcstringOptionalImage thumbnail URLheightnumberOptionalImage height to displaywidthnumberOptionalImage width to display### Upload Image

[](#upload-image)

**POST** `writeaway:images:upload` to upload an image file.

Example request:

`image` - FormData file

Example response:

```
{
  "status": 200,
  "data": [
    {
      "id": "unique-id",
      "src": "image1.png"
    }
  ]
}
```

> For possible image fields see the previous endpoint.

### Delete Image

[](#delete-image)

**POST** or **DELETE** `writeaway:images:delete` to delete a particular image

Example request:

```
{
  "id": "unique-id"
}
```

Example response:

```
{
  "status": 200
}
```

### Get Piece

[](#get-piece)

**GET** or **POST** `writeaway:pieces:get` to fetch a particular piece by its `id` and `type`.

Example request:

```
{
  "id": "unique-id",
  "type": "piece-type"
}
```

> If no pieces found, a new one wil be created. `id` is a unique value across all pieces.

Example response:

```
{
  "status": 200,
  "data": {
    "id": "unique-id",
    "type": "piece-type",
    "data": {
      "key": "value",
      "key...": "value..."
    }
  }
}
```

In case if validation errors the example response will be:

```
{
  "status": 400,
  "errors": {
    "field-name": "error-message",
    "field-name...": "error-message..."
  }
}
```

### Get Pieces in bulk

[](#get-pieces-in-bulk)

**GET** or **POST** `writeaway:pieces:bulk` to fetch a particular pieces by theirs `id` and `type`.

Example request:

```
{
  "pieces": [
    {
      "id": "unique-id",
      "type": "piece-type"
    },
    {
      "id": "unique-id",
      "type": "piece-type"
    }
  ]
}
```

Example response:

```
{
  "status": 200,
  "data": [
    {
      "id": "unique-id",
      "type": "piece-type",
      "data": {
        "key": "value",
        "key...": "value..."
      }
    },
    {
      "id": "unique-id",
      "type": "piece-type",
      "data": {
        "key": "value",
        "key...": "value..."
      }
    }
  ]
}
```

> Not found pieces will be ignored.

In case if validation errors the example response will be:

```
{
  "status": 400,
  "errors": {
    "field-name": "error-message",
    "field-name...": "error-message..."
  }
}
```

### Save Piece

[](#save-piece)

**POST** `writeaway:pieces:save` to save a particular piece by its `id` and `type`.

Example request:

```
{
  "id": "unique-id",
  "type": "piece-type",
  "data": {
    "key": "value",
    "key...": "value..."
  }
}
```

> If no pieces found, a new one wil be created. `id` is a unique value across all pieces.

Example response:

```
{
  "status": 200,
  "data": {
    "id": "unique-id",
    "type": "piece-type",
    "data": {
      "key": "value",
      "key...": "value..."
    }
  }
}
```

In case if validation errors the example response will be:

```
{
  "status": 400,
  "errors": {
    "field-name": "error-message",
    "field-name...": "error-message..."
  }
}
```

Components
----------

[](#components)

### Meta

[](#meta)

Meta is a structure designed to represent current piece editor. While this package knows nothing about real app actors, `\Spiral\Writeaway\Service\Meta\ProviderInterface` is given - a developer can bind it to a more rich implementation, so the meta will contain the real user's id, label and time. Example:

```
{
  "id": "some user id",
  "label": "some user label, such as name",
  "time": "current date time string"
}
```

###  Health Score

26

—

LowBetter than 41% of packages

Maintenance0

Infrequent updates — may be unmaintained

Popularity25

Limited adoption so far

Community15

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 80% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~168 days

Total

5

Last Release

1386d ago

PHP version history (3 changes)v0.1.0-alphaPHP ^7.4

v0.4.0PHP &gt;=8.0

0.5.x-devPHP &gt;=8.1

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/796136?v=4)[Anton Tsitou](/maintainers/wolfy-j)[@wolfy-j](https://github.com/wolfy-j)

---

Top Contributors

[![msmakouz](https://avatars.githubusercontent.com/u/67324318?v=4)](https://github.com/msmakouz "msmakouz (4 commits)")[![butschster](https://avatars.githubusercontent.com/u/773481?v=4)](https://github.com/butschster "butschster (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/spiral-writeaway/health.svg)

```
[![Health](https://phpackages.com/badges/spiral-writeaway/health.svg)](https://phpackages.com/packages/spiral-writeaway)
```

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.5k5.9M738](/packages/sylius-sylius)[phpro/grumphp

A composer plugin that enables source code quality checks.

4.3k16.7M1.0k](/packages/phpro-grumphp)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.4M203](/packages/sulu-sulu)[api-platform/doctrine-common

Common files used by api-platform/doctrine-orm and api-platform/doctrine-odm

274.4M48](/packages/api-platform-doctrine-common)[oat-sa/tao-core

TAO core extension

66143.7k124](/packages/oat-sa-tao-core)[chartmogul/chartmogul-php

ChartMogul API PHP Client

181.5M](/packages/chartmogul-chartmogul-php)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
