๐ BIG NEWS ๐ โฆ Avo 4 has officially SHIPPED โฆ ๐ the beta is over, 4.0 is here โฆ ๐ ๏ธ build admin panels, dashboards & internal tools at light speed โฆ โญ you are visitor #1,136,489 โฆ ๐ tell a friend โฆ best viewed in Ruby on Rails โฆ ๐ click here to see what’s new โฆ
JSON API
Expose your Avo resources as a JSON API for integrations, mobile apps, and headless front-ends.
# $30/mo
gem "avo-api"
An AI agent, a partner integration, a mobile client, a headless front-end:
each one needs the same thing before it can do anything useful, a way to read
and write your data without handing over the keys to everything. This add-on
gives you that on day one. Run the install generator and every Avo resource
becomes a documented REST API over plain JSON, with a full set of endpoints,
GET,
POST,
PATCH,
PUT, and
DELETE
under /api/resources/v1/<resource>.
Each endpoint reuses your existing resource definition, so the fields, the
pagination, and the sorting all match the admin you already built. No
serializers to write, no routes to wire up.
What makes it safe to point an LLM tool or an outside client at your database
is that the API answers to the rules you already wrote. Your Pundit policies
run on every request, so a caller can only read and change what its user is
allowed to, and field visibility follows the same
:index,
:show,
:new, and
:edit
rules your resources declare. Authentication is yours to set: a generated
setup_authentication hook lets you check an API key,
HTTP Basic credentials, or whatever your app already uses, and anything that
fails comes back as a clean 401. The access model is
the part that is slow and risky to get right yourself, and here it is the same
one already guarding your admin.
What it looks like
Add the gem and run one generator. It creates a controller per resource,
inheriting a BaseResourcesController you own:
# Gemfile
gem "avo-api", source: "https://packager.dev/avo-hq/"
$ bundle install
$ rails generate avo_api:install
The API exposes exactly the fields your resource already shows, per view.
hide_on and only_on carry
straight over, so an internal note stays out of the index payload:
class Avo::Resources::Team < Avo::BaseResource
def fields
field :id, as: :id
field :name, as: :text
field :url, as: :text
field :internal_notes, as: :text, hide_on: :index
field :logo, as: :external_image, only_on: :show
end
end
Authorization is your existing Pundit policy, enforced on every request, the same one guarding your admin. Authentication is a hook you fill in, here a shared API key:
class Avo::Api::Resources::V1::UsersController < BaseResourcesController
def setup_authentication
expected = ENV.fetch("API_KEY")
provided = request.headers["Authorization"]&.sub(/^ApiKey /, "")
unless ActiveSupport::SecurityUtils.secure_compare(provided.to_s, expected)
raise Avo::Api::AuthenticationError
end
end
end
From the caller's side it is plain JSON over the verbs you expect:
$ curl -X POST http://localhost:3000/api/resources/v1/teams \\
-H "Authorization: ApiKey $API_KEY" \\
-H "Content-Type: application/json" \\
-d '{ "team": { "name": "Platform", "url": "https://platform.dev" } }'
# 201 Created
# { "record": { "id": 3, "name": "Platform", "url": "https://platform.dev" } }
See it in action
What you get
-
Automatic REST endpoints for every Avo resource, with
index,show,create,update, anddestroy -
Field visibility that mirrors your resource views, so the API exposes exactly what
:indexand:showalready show - Your Pundit policies enforced on every request, the same authorization that guards your Avo admin
-
A generated
setup_authenticationhook for an API key, HTTP Basic, or your own scheme, with failures returned as401 -
A
BaseResourcesControllerin your app that you can override per resource when you need to - JSON request and response shapes that match your records, with validation errors returned as 422s
Why it pays off
- Give an AI agent, a partner, or a new client a documented API to your whole admin in an afternoon, instead of writing serializers and routes resource by resource.
- The API answers to the Pundit policies you already wrote, so you are not maintaining a second permission model for external callers. Authorization stays in one place, and it is the place you already trust.
- Your data never leaves your Rails app. The API runs inside your codebase, so there is no third-party service sitting between an integration and your database.
- Every Avo release makes it better: the endpoints, serialization, and field handling stay aligned with your resource definitions and keep working through upgrades, without you patching them.
- One less internal service for your team to build, secure, and support, and no per-seat pricing as the clients calling it grow.
# included in
# ready to ship?
You ship it this afternoon. We keep it solid for years.