# Pliny: a Ruby skeleton for APIs with endpoints, mediators and schemas

> Pliny bundles the patterns its authors arrived at after writing many APIs, and it ships them as a generator: pliny-new creates an app, pliny-generate produces models, mediators, endpoints, serializers, migrations and JSON schemas, and pliny-update pushes template changes into an existing app. It is opinionated to a fault, which is the point and also the cost.

**interagent/pliny** — An opinionated toolkit for writing excellent APIs in Ruby.

- Repository: https://github.com/interagent/pliny
- Stars: 811 · Forks: 75
- Language: Ruby
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/interagent-pliny

## An opinionated skeleton, not a library of building blocks

Pliny is described as an opinionated toolkit for writing excellent APIs in Ruby, and it says it bundles the best patterns, libraries and practices its authors have seen after writing a lot of APIs. The word opinionated is doing the load-bearing work here. This is not a set of mixin helpers you drop into a Rails app. It is a generated application skeleton with a fixed directory layout, and the generators write files into that layout, including tests, so the structure of your API is decided before you write a line of application code. The meta section records the provenance, created by Brandur Leach and Pedro Belo, and the project is MIT licensed with a wiki and a Google Groups mailing list rather than a rendered documentation site. That shape matters for evaluation. You are adopting a house style, which is valuable if you want one and expensive if you do not.

## Install the gem, then generate the app

The setup is two steps. The gem installs with:

```bash
$ gem install pliny
```

and then the generator creates a new API application and installs it:

```bash
$ pliny-new myapp
$ cd myapp && bin/setup
```

So the deliverable is a working directory with the dependencies, database and test harness already configured, rather than a gem you add to a Gemfile. That is a different adoption path from a normal dependency, and it is worth deciding early whether you want a template or a library. The commands section lists the operational tooling the generated app comes with: foreman start to start the server, foreman run bin/console for an IRB or Pry console, and foreman run bin/run 'puts "hello world"' to run automated code, with a reminder not to forget the foreman run prefix in development. The Rake tasks are the other half of the generated toolchain, covering db:create, db:drop, db:migrate, db:rollback, db:schema:dump, db:schema:load, db:schema:merge, db:seed, db:setup and a schema task that rebuilds schema.json.

## Generators write the file and the test together

The generators are where the conventions become visible, because every one of them produces a source file and a spec in the same run. A model generator creates the model file, a migration and the model spec:

```bash
$ bundle exec pliny-generate model artist
created model file ./lib/models/artist.rb
created migration ./db/migrate/1408995997_create_artists.rb
created test ./spec/models/artist_spec.rb
```

A mediator generator creates the mediator and its spec, an endpoint generator creates the endpoint plus a spec and an acceptance spec and tells you the route to mount, and a schema generator writes a YAML schema file under schema/schemata and rebuilds schema.json. The available commands are endpoint, mediator, migration, model, scaffold, schema and serializer, with scaffold generating an endpoint, model, schema and serializer together. The mediators are the piece worth understanding, because that is the layer that does not exist in a typical Rails controller: a mediator sits between the endpoint and the model, which is the arrangement that keeps business logic out of the HTTP layer. Whether you accept that as a good idea is the central opinion the toolkit is asking you to share.

## Endpoints, mediators and schemas are the three layers

Reading the generated paths tells you the architecture. Endpoints live under lib/endpoints, mediators under lib/mediators, models under lib/models, and the endpoint generator tells you to add a mount line to lib/routes.rb. That last detail is telling, because it means routing is explicit and handwritten rather than generated by a Rails-style convention. The endpoint generator also creates an acceptance spec, so there is a test at the HTTP boundary and a separate test at the mediator boundary, which is a way of keeping the two layers independently verifiable. Schemas are a first-class artefact rather than an afterthought: schema/schemata holds one YAML file per resource and schema.json is a rebuilt aggregate, with a rake schema task to regenerate it. Serializers are generated separately from schemas, so the wire representation and the schema description are separate concerns that a generator can both write. None of this is unusual in isolation, but the fact that all of it arrives pre-wired is the value proposition.

## pliny-update pushes template changes into your app

The most interesting command is pliny-update, used to update the Pliny app in the current directory. The README says this does not only bump the version dependency, but also applies any changes that happened in the template app, for instance a new initializer or tweaks in the base endpoint. That is a meaningful difference from a normal dependency upgrade. A gem update normally changes behaviour in your app without changing your app's files; pliny-update also edits your files, bringing them in line with a newer template. The benefit is that a skeleton that has drifted from the template can be brought back. The cost is that your application files are now modified by a tool, which means merge conflicts are possible and that you should read the diff rather than accept it blindly. There is no rollback path described in the README, which is the kind of thing to check before you use it on a branch with real work on it.

## Testing is RSpec, and the gem has its own suite

The generated application is tested with RSpec, and both a whole suite and a single file are shown in the README:

```bash
$ bundle exec rake
```

```bash
$ bundle exec rspec spec/acceptance/artists_spec.rb
```

The second command is worth noting because it is the acceptance spec specifically, which is the layer that exercises the endpoint. The gem itself is developed the same way, with a spec/ directory, an .rspec file, a Rakefile, a pliny.gemspec and a Gemfile. The style configuration is present too, with .rubocop.yml plus two rubocop StandardRB files, a .rubocop_standardrb.yml and a .rubocop_standardrb_overrides.yml, which tells you the project lints against StandardRB conventions rather than plain RuboCop defaults. Developing the gem itself requires a local database, since the README's development section asks you to run bundle install, then createdb pliny-gem-test, then rake. The CHANGELOG.md and CONTRIBUTING.md at the root are the other two files to look at before contributing.

## Version 1.1.0 is the newest tag, and the branch is still moving

On maintenance, the picture is mixed and you should read it carefully. The release list shows v0.30.0 on 2020-12-14, v1.0.0 on 2023-10-09 and v1.1.0 on 2024-02-13. The repository is not archived and the last push was on 2026-04-29, which is more than five months before today. So the branch is still receiving work, but the newest tagged release is more than two years old, and the gap between the tag and the branch has not been closed with a release. For a project whose value is the template, that matters in a specific way. The generated app and the pliny-update tool both come from the template, so what a new user gets is whatever the current branch holds rather than the 1.1.0 tag, and what pliny-update applies to an existing app may differ from what pliny-new produced at 1.1.0. The licence is MIT with a LICENSE file at the root, so there is no obstacle to forking the template if you would rather freeze it.

## Conclusion

Adopt Pliny if you are starting a Ruby API and want the endpoint, mediator and schema conventions of an established codebase rather than designing your own layer boundaries. Do not adopt it for an existing application, because its generators assume a fresh skeleton and its conventions are not something you retrofit cleanly. Before you commit, read the wiki, since the README is an index of commands rather than a design document, and check the release history, because the newest tagged release is v1.1.0 from 2024-02-13 while the last push was on 2026-04-29.

## FAQ

### What is Pliny?

It is an MIT licensed Ruby toolkit described as opinionated, for writing and maintaining APIs. It bundles patterns, libraries and practices its creators accumulated while writing many APIs, and it ships generators for models, mediators, endpoints, migrations, schemas, serializers and scaffolds.

### How do I create a new API app with Pliny?

Run gem install pliny, then pliny-new myapp and cd myapp && bin/setup. The generated app comes with its dependencies, database and test harness already configured, rather than being a gem you add to an existing Gemfile.

### What does pliny-update do?

It updates the Pliny app in the current directory. The README says it does not only bump the version dependency but also applies changes that happened in the template app, such as a new initializer or tweaks in the base endpoint, so it edits your application files.

### Which Ruby and testing tools does Pliny use?

The generated application is tested with RSpec, run through bundle exec rake for the whole suite or bundle exec rspec for a single file, and the gem's own development setup runs bundle install, createdb pliny-gem-test and rake. The project lints with RuboCop configured for StandardRB, with .rubocop.yml and two rubocop StandardRB files.

## Sources

- [interagent/pliny on GitHub](https://github.com/interagent/pliny)
- [Issues](https://github.com/interagent/pliny/issues)
- [License: MIT](https://github.com/interagent/pliny/blob/main/LICENSE)
- [README](https://github.com/interagent/pliny/blob/main/README.md)
- [Releases](https://github.com/interagent/pliny/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/interagent-pliny
