Skip to main content
Restricted access. Public API v2 is currently available only to allowlisted organizations. Requests from workspaces that have not been enabled are rejected. Contact your Reevo representative to have your organization added to the allowlist.

Objects

Public API v2 treats standard objects and custom objects as records with typed attributes. Every record has:
  • id: the record UUID
  • record_type: the public object name, such as contact, account, or opportunity
  • attributes: the record’s fields, rendered as typed values
  • created_at and updated_at: ISO 8601 timestamps, present at the top level of the record (updated_at is nullable and may be null at the top level; the same values are also available as typed envelopes inside attributes)

Reading values

Read responses use value envelopes. Each envelope includes a value_type discriminator and a value.
{
  "id": "9b4f2fb1-2a7f-4d75-8d5f-3f3f0d7f2a7a",
  "record_type": "contact",
  "attributes": {
    "first_name": {
      "value_type": "string",
      "value": "Sarah"
    },
    "stage": {
      "value_type": "contact_stage",
      "value": {
        "id": "8b8c2b1d-56c1-4b52-84f3-d00d4b8bb1ef",
        "api_name": "working",
        "display_name": "Working",
        "color": "#6966FF"
      }
    }
  }
}
Reevo defines a fixed set of value types. See Value Types for the full catalog and the per-type read, write, and filter behavior, including Record References and Selects and Stages.

Writing values

Create and patch requests use an attributes object. For many fields, you can write raw values:
{
  "attributes": {
    "first_name": "Sarah",
    "last_name": "Chen",
    "primary_email": "sarah.chen@acme.com"
  }
}
You can also write enveloped values when you want the request shape to match read responses:
{
  "attributes": {
    "first_name": {
      "value_type": "string",
      "value": "Sarah"
    },
    "primary_email": {
      "value_type": "email",
      "value": "sarah.chen@acme.com"
    }
  }
}
Reference fields — attributes that point at another record, such as owner_user_id or an opportunity’s account_id — are ordinary attributes. Set them inside the attributes object on create, _upsert, and patch, just like any other field; there is no separate relationships block on the write body. A reference value can be given three ways:
  • A bare id — the target record’s UUID as a string.
  • A { field, value } match against a unique field on the target record.
  • A full record_reference envelope, for example { "value_type": "record_reference", "value": { "related_record_id": "…", "related_record_type": "account" } }.
See Record References for the full form catalog and per-form behavior. The { field, value } match resolves the target by that field, so the field must be unique on the target record type. Check which fields are unique in the record’s schema — each attribute carries an is_unique flag in _schema (see Schema and Resources). A non-unique or unrecognized match field is rejected with invalid_matching_field. User references — such as owner_user_id — can be matched by email:
{
  "attributes": {
    "owner_user_id": {
      "field": "email",
      "value": "person@company.com"
    }
  }
}
On PATCH, omitted fields are left unchanged. Sending null clears a nullable field. Some computed and custom fields populate asynchronously: they may be absent or unset in the immediate create or patch response and backfill shortly afterward. Re-read the record with GET /{id} if you need those values rather than relying on the write response to contain them.

Querying records

Use POST /api/v2/public/<record_type>/_query to filter, sort, and paginate records.
{
  "filters": [
    {
      "field": "primary_email",
      "operator": "eq",
      "value": "sarah.chen@acme.com"
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ],
  "limit": 50
}
Multiple top-level filters are combined with and. More complex filters can use and, or, and not groups.
{
  "filters": [
    {
      "or": [
        {
          "field": "primary_email",
          "operator": "contains",
          "value": "@acme.com"
        },
        {
          "field": "title",
          "operator": "contains",
          "value": "founder"
        }
      ]
    }
  ]
}
Query responses wrap records as { "data": [...], "pagination": {...} }. When more results are available, the opaque cursor is at pagination.next_cursor. Pass that cursor into the next _query request. See Pagination for page size, the pagination block, and cursor lifetime, and Query Records for Sync for incremental sync patterns.

Relationships

Relationships connect records without embedding every related record in the parent response. Examples:
  • contact -> accounts
  • contact -> opportunities
  • account -> contacts
  • opportunity -> contacts
  • Custom object relationships by api_name
Use relationship endpoints when you need to list, add, update, or remove links:
/api/v2/public/contact/{contact_id}/relationship/accounts
/api/v2/public/account/{account_id}/relationship/contacts
/api/v2/public/{object_api_name}/{record_id}/relationship/{api_name}
Some relationships use a junction record. A junction record stores data about the relationship itself, such as a role or primary flag. See Manage Relationships for cardinality, junction edges, and the full relationship workflow.

Where to go next