API reference · v1

Apivera REST API

A typed, resource-oriented API over the same domain the workspace uses. JSON bodies, bearer authentication, cursor-free pagination and predictable error codes.

Base URL https://api.apivera.ioJSON only600 req/min

Authenticating a request

Exchange organization credentials for a short-lived access token, then send it as a bearer header.

Request token
curl -X POST https://api.apivera.io/v1/auth/token \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "org_goldenacre",
    "client_secret": "sk_live_•••••••••••",
    "scope": "hives:read inspections:write"
  }'
Token response
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "organization_id": "org_goldenacre",
  "role": "OPS_MANAGER",
  "scopes": ["hives:read", "inspections:write"]
}
Authenticated call
curl https://api.apivera.io/v1/hives?status=ACTIVE&per_page=25 \
  -H "Authorization: Bearer $APIVERA_TOKEN" \
  -H "Accept: application/json"
TypeScript client
import { Apivera } from "@apivera/sdk";

const client = new Apivera({ token: process.env.APIVERA_TOKEN! });

const { data, meta } = await client.hives.list({
  status: "ACTIVE",
  apiaryId: "api_7fd2c1",
  perPage: 50,
});

console.log(meta.total, data[0].tag);

Apiaries endpoints

Yards that hold colonies, with capacity, coordinates and forage profile.

3 endpoints
GET/v1/apiariesapiaries:read

List apiaries in the current organization.

ParameterTypeDescription
statestringFilter by two-letter state code.
pageinteger1-indexed page number, default 1.
per_pageintegerPage size, 1–100, default 25.
Response
{
  "data": [
    {
      "id": "api_7fd2c1",
      "name": "Coyote Ridge",
      "code": "CR-04",
      "latitude": 36.7412,
      "longitude": -119.7846,
      "county": "Fresno",
      "state": "CA",
      "forage_profile": "Almond, mustard cover",
      "capacity": 320,
      "hive_count": 288,
      "manager_id": "usr_beekeeper",
      "created_at": "2026-01-18T14:05:00Z"
    }
  ],
  "meta": { "page": 1, "per_page": 25, "total": 34 }
}
POST/v1/apiariesapiaries:write

Create a yard.

Request body
{
  "name": "Coyote Ridge",
  "code": "CR-04",
  "latitude": 36.7412,
  "longitude": -119.7846,
  "county": "Fresno",
  "state": "CA",
  "forage_profile": "Almond, mustard cover",
  "capacity": 320,
  "manager_id": "usr_beekeeper"
}
Response
{
  "data": { "id": "api_7fd2c1", "code": "CR-04", "capacity": 320 },
  "audit": { "id": "aud_91ba22", "action": "apiary.created" }
}
DELETE/v1/apiaries/{id}apiaries:write

Delete an empty yard.

Response
{
  "error": {
    "code": "apiary_not_empty",
    "message": "Move or archive the hives in this apiary before deleting it.",
    "hint": "288 colonies are still assigned to CR-04."
  }
}

Error codes

Every failure returns a machine-readable code and a human hint.

  • 401

    unauthorized

    Missing, expired or malformed bearer token.

  • 403

    insufficient_scope

    The token's role cannot reach this module.

  • 404

    not_found

    Record absent or outside the caller's organization.

  • 409

    rule_violation

    A critical rule rejected the write; see details.

  • 422

    validation_failed

    Payload failed schema validation.

  • 429

    rate_limited

    600 requests per minute per organization.

Webhooks

Signed with HMAC SHA-256 over the raw body; retried with backoff for 24 hours.

  • inspection.created

    Fires after a field record is committed.

  • hive.status_changed

    Colony status transitions, including quarantine.

  • move.delivered

    Load arrival with placement counts.

  • contract.deployed

    Contract entered the deployed state.

  • invoice.issued

    Grower invoice generated for a contract.

Signature verification
const expected = crypto
  .createHmac("sha256", process.env.APIVERA_WEBHOOK_SECRET!)
  .update(rawBody)
  .digest("hex");

if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
  return res.status(401).json({ error: "invalid_signature" });
}

Pagination and idempotency

Conventions that apply to every collection and write endpoint.

Paginated response envelope
{
  "data": [ /* records */ ],
  "meta": {
    "page": 3,
    "per_page": 25,
    "total": 4180,
    "total_pages": 168
  },
  "links": {
    "next": "/v1/hives?page=4&per_page=25",
    "prev": "/v1/hives?page=2&per_page=25"
  }
}
Idempotent write
curl -X POST https://api.apivera.io/v1/moves \
  -H "Authorization: Bearer $APIVERA_TOKEN" \
  -H "Idempotency-Key: mov-2027-02-06-cr04-rivera3" \
  -H "Content-Type: application/json" \
  -d '{ "origin_apiary_id": "api_7fd2c1", "hive_count": 208 }'