# API Field Documentation
## Overview
This document describes the fields in the API response, including their definitions and logic used for computation.
### How to generate an API token
```ruby
my_key = ApiKey.create!(consumer_name: "Example key")
token = my_key.key_string
```
### Defined route and controller files
```ruby!
namespace :v2 do
resources :appeals, only: :index
end
```
The most relevant controller file is: `app/controllers/api/v2/appeals_controller.rb`
and the data is primarily generated via this file: `app/services/api/v2/appeals.rb`
### Serializers
There are 4 relevant serializers for this API.
Higher-Level Reviews: `app/models/serializers/v2/hlr_status_serializer.rb`
Supplemental Claims: `app/models/serializers/v2/sc_status_serializer.rb`
Appeals: `app/models/serializers/v2/appeal_status_serializer.rb`
Legacy Appeals: `app/models/serializers/v2/legacy_appeal_status_serializer.rb`
### Example curl request to the api
```
curl -X GET -H "Authorization: Token dba6a974c0de4e33996a33c0eac886d0" -H "Content-Type: application/json" -H "X-VA-Receipt-Date: 2025-02-05" -H "ssn: 252866460" "http://localhost:3000/api/v2/appeals"
```
### Example api return
```json
{
"data": [
{
"id": "HLR80",
"type": "higherLevelReview",
"attributes": {
"appealIds": ["HLR80"],
"updated": "2025-02-06T17:01:16-05:00",
"incompleteHistory": false,
"active": true,
"description": "Streptococcic arthritis",
"location": "aoj",
"aoj": "vha",
"programArea": "medical",
"status": {
"type": "hlr_received",
"details": {}
},
"alerts": [],
"issues": [
{
"active": true,
"lastAction": null,
"date": null,
"description": "Streptococcic arthritis",
"diagnosticCode": "5008"
}
],
"events": [
{
"type": "hlr_request",
"date": "2024-12-30"
}
],
"evidence": []
}
}
]
}
```
## Fields
### `appeal_ids`
#### Attribute Description
Resolved by `linked_review_ids`, which is an array containing a single string.
#### Possible values
`string` since it's an infinite number of integers
#### Code snippets
```ruby
def review_status_id
"HLR#{id}"
end
def linked_review_ids
Array.wrap(review_status_id)
end
```
### `updated`
#### Attribute Description
Always the current time, converted to Eastern Time and rounded into an ISO 8601 date string.
#### Possible values
`ISO 8601 date string`
#### Code snippets
```ruby
Time.zone.now.in_time_zone("Eastern Time (US & Canada)").round.iso8601
```
### `incomplete_history`
#### Attribute Description
Always `false` for non-legacy appeals. For legacy appeals it is marked as true if any of the nodes of the generated appeal series is marked as incomplete which is a node without a parent in the tree
#### Possible values
`boolean` : true or false
#### Code snippets
```ruby
# for other review types
attribute :incomplete_history do
false
end
# For legacy appeals
appeal_tree_nodes.each do |node|
# Set the series, joining through the merge table to the series table.
appeal_series = series_table[merge_table[node[:series_id]]]
appeal_series.appeals << node[:appeal]
# If any node is marked as incomplete, the series is marked as incomplete.
appeal_series.update(incomplete: true) if node[:incomplete]
end
```
### `active`
#### Attribute Description
A boolean indicating active status, determined by the `active_status?` method. Factors include benefit type, existing EPS, and active tasks associated with the review.
#### Possible values
`boolean` : true or false
#### Code snippets
```ruby
# For appeals
def active_status?
# For the appeal status api, and Appeal is considered open
# as long as there are active remand claim or effectuation
# tracked in VBMS.
active? || active_effectuation_ep? || active_remanded_claims?
end
# for HLRs active? includes End product check as well
def active_status?
# for the purposes for appeal status api, an HLR is considered active if there are
# still active remand claims.
active? || active_remanded_claims?
end
# SCs same as HLRs but without the active remand check
def active_status?
active?
end
# Legacy appeal
def active?
# All issues on an appeal have not yet been granted or denied
status != "Complete"
end
```
### `description`
#### Attribute Description
A string representing the number of request issues associated with a review. It can be derived from diagnostic codes, claim types, or issue count. Implementation:
#### Possible values
`string` : it can be a very large number of possibilities since it's issue count + benefit types and other things
#### Code snippets
```ruby
def description
return if request_issues.empty?
descripton = fetch_status_description_using_diagnostic_code
return descripton if descripton
description = fetch_status_description_using_claim_type
return description if description
return "1 issue" if request_issues.count == 1
"#{request_issues.count} issues"
end
def fetch_status_description_using_diagnostic_code
issue = request_issues.find do |ri|
!ri[:contested_rating_issue_diagnostic_code].nil?
end
description = issue.api_status_description if issue
return unless description
return description if request_issues.count - 1 == 0
return "#{description} and 1 other" if request_issues.count - 1 == 1
"#{description} and #{request_issues.count - 1} others"
end
def fetch_status_description_using_claim_type
return if program == "other" || program == "multiple"
return "1 #{program} issue" if request_issues.count == 1
"#{request_issues.count} #{program} issues"
end
```
### `aod`
#### Attribute description
An attribute depicting whether or not an appeal or legacy appeal has been marked as advanced on docket. It is resolved by the `advanced_on_docket?` method for appeals and the `aod` attribute on legacy appeals
**Special note: This attribute is only present on Appeals and Legacy Appeals not HLRs and SCs**
#### Possible values
`boolean`: True or false based on the aod status
#### Code snippets
```ruby
# For Appeals. It is based on several different criteria often related to the claimant model
def advanced_on_docket?
conditionally_set_aod_based_on_age
# One of the AOD motion reasons is 'age'. Keep interrogation of any motions separate from `aod_based_on_age`,
# which reflects `claimant.advanced_on_docket_based_on_age?`.
aod_based_on_age || claimant&.advanced_on_docket_motion_granted?(self)
end
#For legacy appeals it comes straight out of Vacols
def aod(vacols_id)
VACOLS::Case.aod([vacols_id])[vacols_id]
end
```
### `location`
#### Attribute description
Always `"aoj"` for SCs and HLRs. For appeals and legacy appeals, determined by active EPs, remands, or latest appeal status. Implementation:
#### Possible values
`enum`: the value can only be "aoj" or "bva" regardless of review type
#### Code snippets
```ruby
# Hlrs and SCs
attribute :location do
"aoj"
end
# Appeals
def location
if active_effectuation_ep? || active_remanded_claims?
"aoj"
else
"bva"
end
end
# Legacy appeals
def location
%w[Advance Remand].include?(latest_appeal.status) ? :aoj : :bva
end
```
### `aoj`
#### Attribute description
Derived from request issues and benefit type. For appeals, it may be "other" if issues have different benefit types. For legacy appeals, it finds the first non-nil `aoj` value from all issues or defaults to "other".
#### Possible values
`string` or possibly `enumeration`: The total number of values seems to be fixed based on all the possible benefit types, the list of aoj values from legacy appeals, and "other". If the legacy aoj values are non variable then it can be considered an enumeration
#### Code snippets
```ruby
# For HLRs and SCs
def aoj
return if request_issues.empty?
request_issues.first.api_aoj_from_benefit_type
end
# For appeals
def aoj
return if request_issues.empty?
return "other" unless all_request_issues_same_aoj?
request_issues.first.api_aoj_from_benefit_type
end
# Legacy appeal version
def aoj
appeals.lazy.flat_map(&:issues).map(&:aoj).find { |aoj| !aoj.nil? } || :other
end
# The request issue method that decides the aoj type
def api_aoj_from_benefit_type
case benefit_type
when "compensation", "pension", "fiduciary", "insurance", "education", "voc_rehab", "loan_guaranty"
"vba"
else
benefit_type
end
end
```
### `program`
#### Attribute description
Determines the benefit type for HLRs and SCs. For appeals, if all request issues share the same benefit type, that type is used; otherwise, it is "multiple".
**Special note: For Appeals, HLRs, and SCs the benefit types listed below get changed to "vba"
"compensation", "pension", "fiduciary", "insurance", "education", "voc_rehab", and "loan_guaranty"**
#### Possible values
`enumeration`: It can only be one of the following values
vre, medical, burial, multiple, compensation, pension, fiduciary, insurance, education, voc_rehab, loan_guaranty, nca, vha, vba_burial, compensation, education, insurance, loan_guaranty, medical, pension, vre, other, bva, nca_burial, vba, or fiduciary
#### Code snippets
```ruby
# HLRs and SCs
def program
case benefit_type
when "voc_rehab"
"vre"
when "vha"
"medical"
when "nca"
"burial"
else
benefit_type
end
end
#Appeal version
def program
return if request_issues.empty?
if request_issues.all? { |ri| ri.benefit_type == request_issues.first.benefit_type }
request_issues.first.benefit_type
else
"multiple"
end
end
# Benefit types
{
"compensation": "Compensation",
"pension": "Pension & Survivor's Benefits",
"fiduciary": "Fiduciary",
"insurance": "Insurance",
"education": "Education",
"voc_rehab": "Veterans Readiness and Employment",
"loan_guaranty": "Loan Guaranty",
"nca": "National Cemetery Administration",
"vha": "Veterans Health Administration"
}
# For legacy appeals it is either one of these values from the constant hash below or "multiple"
PROGRAMS = {
"01" => :vba_burial,
"02" => :compensation,
"03" => :education,
"04" => :insurance,
"05" => :loan_guaranty,
"06" => :medical,
"07" => :pension,
"08" => :vre,
"09" => :other,
"10" => :bva,
"11" => :nca_burial,
"12" => :fiduciary
}.freeze
```
### `status`
#### Attribute description
Fetched via a serializer with attributes `type` and `details`.
```ruby
attribute :type, &:fetch_status
attribute :details, &:fetch_details_for_status
```
##### type attribute
##### Sub Attribute description
A sub attribute of the status attribute that is aliased to the `fetch_status` method
##### Possible values
`enumeration`: The list of values is a fixed number of strings but it is scattered around in 10+ methods: TODO: Build a complete list of values for appeals and legacy appeals
Possible values for `fetch_status`:
- HLR: `:hlr_received`, `:hlr_dta_error`, `:hlr_decision`, and `:hlr_closed`
- SC: `:sc_received`, `:sc_closed`, and `:sc_decision`
- Appeals: Multiple status types including `:pre_docketed`, `:decision_in_progress`, `:bva_decision`, etc.
- Legacy appeals: Same as appeals it includes a large amount of status types
Appeal values
```ruby
:pre_docketed,
:pending_hearing_scheduling,
:scheduled_hearing,
:evidentiary_period,
:at_vso,
:decision_in_progress,
:on_docket,
:ama_remand,
:post_bva_dta_decision,
:bva_decision_effectuation,
:bva_decision,
:decision_in_progress,
:withdrawn,
:other_close
```
Legacy Appeal values:
```ruby
[
:scheduled_hearing,
:pending_hearing_scheduling,
:on_docket,
:pending_certification_ssoc,
:pending_certification,
:pending_form9,
:pending_soc,
:stayed,
:at_vso,
:bva_development,
:decision_in_progress,
:bva_decision,
:field_grant,
:withdrawn,
:ftr,
:ramp,
:statutory_opt_in,
:death,
:reconsideration,
:merged,
:other_close,
:remand_ssoc,
:remand,
:motion,
:cavc
]
```
##### Code snippets
```ruby
# For HLRs
def fetch_status
if active?
:hlr_received
elsif active_remanded_claims?
:hlr_dta_error
elsif remand_supplemental_claims.any?
remand_supplemental_claims.each do |rsc|
return :hlr_decision if rsc.decision_issues.any?
end
:hlr_closed
else
decision_issues.empty? ? :hlr_closed : :hlr_decision
end
end
# For SCs
def fetch_status
if active?
:sc_recieved
else
decision_issues.empty? ? :sc_closed : :sc_decision
end
end
# For appeals and more unlisted chained method calls
def fetch_status
if open_pre_docket_task?
:pre_docketed
elsif active?
fetch_pre_decision_status
else
fetch_post_decision_status
end
end
# for legacy appeals and more unlisted chained method calls
def fetch_status
case latest_appeal.status
when "Advance"
disambiguate_status_advance
when "Active"
disambiguate_status_active
when "Complete"
disambiguate_status_complete
when "Remand"
disambiguate_status_remand
when "Motion"
:motion
when "CAVC"
:cavc
end
end
```
##### description attribute
##### Sub Attribute description
A sub attribute of the status attribute that is aliased to the `fetch_details_for_status` method
##### Possible values
`hash` or `object` - It builds json for all the fetched decision issues on the review based on benefit type and disposition
The json will often end up looking like this. There are other keys for hearings and other types of statuses sometimes
```ruby
{
issues: api_issues_for_status_details_issues(issue_list)
}
# The issues values
{
description: issue.api_status_description,
disposition: issue.api_status_disposition
}
```
##### Code snippets
```ruby
# HLRs
def fetch_details_for_status
case fetch_status
when :hlr_decision
issue_list = fetch_all_decision_issues
{
issues: api_issues_for_status_details_issues(issue_list)
}
else
{}
end
end
# SCs
def fetch_details_for_status
case fetch_status
when :sc_decision
{
issues: api_issues_for_status_details_issues
}
else
{}
end
end
# Appeals
def fetch_details_for_status # rubocop:disable Metrics/MethodLength
case fetch_status
when :bva_decision
{
issues: api_issues_for_status_details_issues(decision_issues)
}
when :ama_remand
{
issues: api_issues_for_status_details_issues(decision_issues)
}
when :post_bva_dta_decision
post_bva_dta_decision_status_details
when :bva_decision_effectuation
{
bva_decision_date: decision_event_date,
aoj_decision_date: decision_effectuation_event_date
}
when :pending_hearing_scheduling
{
type: "video"
}
when :scheduled_hearing
api_scheduled_hearing_status_details
when :decision_in_progress
{
decision_timeliness: AppealSeries::DECISION_TIMELINESS.dup
}
else
{}
end
end
# Legacy Appeals
def fetch_details_for_status
case status
when :scheduled_hearing
hearing = latest_appeal.scheduled_hearings.min_by(&:scheduled_for)
{
date: hearing.scheduled_for.to_date,
type: hearing.readable_request_type.downcase,
location: hearing.request_type_location
}
when :pending_hearing_scheduling
{ type: latest_appeal.current_hearing_request_type }
when :pending_form9, :pending_certification, :pending_certification_ssoc
{
last_soc_date: last_soc_date,
certification_timeliness: CERTIFICATION_TIMELINESS.dup,
ssoc_timeliness: SSOC_TIMELINESS.dup
}
when :pending_soc
{ soc_timeliness: SOC_TIMELINESS.dup }
when :at_vso
{ vso_name: representative_name }
when :decision_in_progress
{ decisionTimeliness: DECISION_TIMELINESS.dup }
when :remand
{
issues: issues_for_last_decision,
remand_timeliness: REMAND_TIMELINESS.dup
}
when :remand_ssoc
{
last_soc_date: last_soc_date,
return_timeliness: RETURN_TIMELINESS.dup,
remand_ssoc_timeliness: REMAND_SSOC_TIMELINESS.dup
}
when :bva_decision
{ issues: issues_for_last_decision }
else
{}
end
end
# Issues get build by this. Which ends up being different based on benefit type and disposition
def api_issues_for_status_details_issues(issue_list)
issue_list.map do |issue|
{
description: issue.api_status_description,
disposition: issue.api_status_disposition
}
end
```
### `alerts`
#### Attribute description
An array of objects that varies based on the type of decision review and relevant data that is sorted by decision date
#### Possible values
`array`: It's an array of objects of this type of structure. The keys change based on the type of alert that is built
```ruby
{
type: "ama_post_decision",
details:
{
decisionDate: decision_review.decision_effectuation_event_date,
availableOptions: decision_review.available_review_options,
dueDate: decision_review.decision_effectuation_event_date + 365.days,
cavcDueDate: decision_review.decision_effectuation_event_date + 120.days
}
}
```
#### Code snippets
```ruby
def alerts
@alerts ||= ApiStatusAlerts.new(decision_review: self).all.sort_by { |alert| alert[:details][:decisionDate] }
end
# Alert types for HLRs and SCs. Only includes the post_decision alert
def claim_review_alerts
[
post_decision
].compact
end
# Appeal alerts are more varied
def appeal_alerts
[
post_decision,
post_remand_decision,
post_effectuation,
evidentiary_period,
scheduled_hearing
].flatten.compact.uniq
end
# The only kind of alerts for HLRs and SCs
def post_decision
return unless decision_review.api_alerts_show_decision_alert?
return unless Time.zone.today <= decision_review.due_date_to_appeal_decision
return if appeal? && Time.zone.today > decision_review.cavc_due_date
{
type: "ama_post_decision",
details:
{
decisionDate: decision_review.decision_date_for_api_alert,
availableOptions: decision_review.available_review_options,
dueDate: decision_review.due_date_to_appeal_decision,
cavcDueDate: appeal? ? (decision_review.decision_date_for_api_alert + 120.days) : nil
}
}
end
# Example of a different kind of alert. This one is hearing related
def scheduled_hearing
return unless decision_review.hearing_docket?
scheduled_hearing = decision_review.scheduled_hearing
return unless scheduled_hearing
{
type: "scheduled_hearing",
details: {
date: scheduled_hearing.scheduled_for.to_date,
type: decision_review.api_scheduled_hearing_type
}
}
end
```
### `issues`
#### Attribute description
Uses the normal issue serializer to serialize all active request issues or decision issues on the review
#### Possible values
`object` or `hash`: It's an object of objects for all active issues on the review. The total possible combination of values is very large since it reuses the normal IssueSerializer
The attributes on the issue serializer is listed below in the code snippets. These chain into some of the methods listed above for some of the other attribute fields as well like the `api_status_description`
#### Code snippets
```ruby
def issues(object)
IssueSerializer.new(object.active_request_issues_or_decision_issues, is_collection: true)
.serializable_hash[:data].collect { |issue| issue[:attributes] }
end
# Issue serializer attributes
attribute :active, &:api_status_active?
attribute :last_action, &:api_status_last_action
attribute :date, &:api_status_last_action_date
attribute :description, &:api_status_description
attribute :diagnostic_code, &:diagnostic_code
# Legacy appeal issues are generated by the AppealSeriesIssues rather than the Issues serializer
def issues
@issues ||= AppealSeriesIssues.new(appeal_series: self).all
end
```
#### Last action Issue attribute
The last action attribute is the disposition of the issue for HLRs, SCs, and Appeals. It is resolved by the `api_status_last_action` method for all 3 types.
For request issues the return value is always nil
```ruby!
def api_status_last_action
# this will be nil
# may need to be updated if an issue is withdrawn
end
```
For decision issues the disposition is returned or "remand" if it was a "remanded disposition"
```ruby!
def api_status_last_action
return "remand" if disposition == "remanded"
disposition
end
```
The disposition list for Appeals. It comes from the `client/constants/ISSUE_DISPOSITIONS_BY_ID.json` json file
```json
{
"allowed": "Allowed",
"remanded": "Remanded",
"denied": "Denied",
"vacated": "Vacated",
"dismissed_death": "Dismissed, Death",
"dismissed_matter_of_law": "Dismissed, Matter of Law",
"withdrawn": "Withdrawn",
"stayed": "Stayed"
}
```
The disposition list for HLRs and SCs through Caseflow
```javascript!
export const DISPOSITION_OPTIONS = ['Granted', 'Denied', 'DTA Error', 'Dismissed', 'Withdrawn'];
```
LegacyAppeals is a bit more difficult since the data comes out of vacols but the issues last action type should have to match one of the values from this hash in the AppealsSeriesIssues model
```ruby!
LAST_ACTION_TYPE_FOR_DISPOSITIONS = {
allowed: [
:allowed
],
denied: [
:denied
],
remand: [
:remanded,
:manlincon_remand
],
field_grant: [
:benefits_granted_by_aoj,
:advance_allowed_in_field
],
withdrawn: [
:withdrawn,
:motion_to_vacate_withdrawn,
:withdrawn_from_remand,
:recon_motion_withdrawn,
:advance_withdrawn_by_appellant_rep,
:advance_failure_to_respond,
:remand_failure_to_respond,
:ramp_opt_in
]
}.freeze
```
The one exception to that is that :cavc_remand is also a possible type added by the method itself under certain conditions
```ruby!
def last_action_for_issues(issues)
issues.reduce(date: nil, type: nil) do |memo, issue|
if issue.close_date && (memo[:date].nil? || issue.close_date > memo[:date])
type = last_action_type_from_disposition(issue.disposition)
if type
# Prevent draft decisions from being shared publicly
unless [:allowed, :denied, :remand].include?(type) && issue.appeal.activated?
memo[:date] = issue.close_date
memo[:type] = type
end
end
end
last_cavc_remand = issue.cavc_decisions.select(&:remanded?).max_by(&:decision_date)
if last_cavc_remand && (memo[:date].nil? || last_cavc_remand.decision_date > memo[:date])
memo[:date] = last_cavc_remand.decision_date
memo[:type] = :cavc_remand
end
memo
end
end
```
##### Possible values for HLRs and SCs should be
```ruby!
['Granted', 'Denied', 'DTA Error', 'Dismissed', 'Withdrawn']
```
##### Possible values for Appeals should be
```ruby!
["allowed", "remanded", "denied", "vacated", "dismissed_death", "dismissed_matter_of_law", "withdrawn", "stayed"]
```
##### Possible values for legacy appeals should be
```ruby!
[:allowed,
:denied,
:remanded,
:manlincon_remand,
:benefits_granted_by_aoj,
:advance_allowed_in_field,
:withdrawn,
:motion_to_vacate_withdrawn,
:withdrawn_from_remand,
:recon_motion_withdrawn,
:advance_withdrawn_by_appellant_rep,
:advance_failure_to_respond,
:remand_failure_to_respond,
:ramp_opt_in,
:cavc_remand]
```
### `docket`
#### Attribute description
An attribute that contains docket information based on the type of docket, whether or not it's eligible for docket switch, and receipt date of the Appeal
**Special Note: This attribute only applies to Appeal and Legacy Appeals not to HLRs or SCs**
#### Possible values
`object`: An object that contains docket information described above and below
#### Code snippets
```ruby
# For Appeals
def docket_hash
return unless active_status?
return if location == "aoj"
{
type: fetch_docket_type,
month: Date.parse(receipt_date.to_s).change(day: 1),
switchDueDate: docket_switch_deadline,
eligibleToSwitch: eligible_to_switch_dockets?
}
end
# For legacy appeals it is built a little differently based on data retrieved from vacols
def fetch_docket
return unless active? && %w[original post_remand].include?(type_code) && form9_date && !aod
DocketSnapshot.latest.docket_tracer_for_form9_date(form9_date)
end
# It should eventually end up looking like these DocketTracer hashes
def to_hash
{
front: at_front,
total: docket_count,
ahead: ahead_count,
ready: ahead_and_ready_count,
month: month,
docketMonth: latest_docket_month,
eta: nil
}
end
```
### `events`
#### Attribute description
Generated by the `AppealEvents` model, differing for each decision review.
#### Possible values
`array`: An array of objects generated by the AppealEvents class
#### Code snippets
```ruby
def events
@events ||= AppealEvents.new(appeal: self).all
end
# HLR events for example
def hlr_events
[
hlr_request_event,
hlr_decision_event,
hlr_dta_error_event,
dta_decision_event,
hlr_other_close_event
].flatten.uniq.select(&:valid?)
end
def hlr_decision_event
AppealEvent.new(type: :hlr_decision, date: appeal.decision_event_date)
end
# The appeal event to_hash method
def to_hash
{ type: type, date: date.to_date }
end
# So the resulting value would look like for one of the hlr events
{ type: :hlr_decision, date: appeal.decision_event_date }
```
### `evidence`
#### Attribute description
Always an empty array; a stubbed method.
#### Possible values
`array` always an empty array
#### Code snippets
```ruby
attribute :evidence do
[]
end
```
### `type`
#### Attribute description
The type attribute only exists on Appeals and LegacyAppeals. It is the steam type of the appeal or 'Original'. The values are pulled from the `client/constants/AMA_STREAM_TYPES.json` file for appeals.
It is comes from these values for LegacyAppeals
```ruby
TYPE_CODES = {
"Original" => "original",
"Post Remand" => "post_remand",
"Reconsideration" => "reconsideration",
"Court Remand" => "post_cavc_remand",
"Clear and Unmistakable Error" => "cue"
}.freeze
```
#### Possible values
**Appeals:**
`string`: ["Original", "Vacate", "De Novo", "Court Remand"]
**Legacy Appeals:**
`string`: ["original", "post_remand", "reconsideration", "post_cavc_remand", "cue", "other"]
#### Code snippets
```ruby
enum stream_type: {
Constants.AMA_STREAM_TYPES.original.to_sym => Constants.AMA_STREAM_TYPES.original,
Constants.AMA_STREAM_TYPES.vacate.to_sym => Constants.AMA_STREAM_TYPES.vacate,
Constants.AMA_STREAM_TYPES.de_novo.to_sym => Constants.AMA_STREAM_TYPES.de_novo,
Constants.AMA_STREAM_TYPES.court_remand.to_sym => Constants.AMA_STREAM_TYPES.court_remand
}
def type
stream_type&.titlecase || "Original"
end
{
"original": "original",
"vacate": "vacate",
"de_novo": "de_novo",
"court_remand": "court_remand"
}
# For legacy appeals
# Codes for Appeals Status API
TYPE_CODES = {
"Original" => "original",
"Post Remand" => "post_remand",
"Reconsideration" => "reconsideration",
"Court Remand" => "post_cavc_remand",
"Clear and Unmistakable Error" => "cue"
}.freeze
def type_code
TYPE_CODES[type] || "other"
end
```
## Additional Considerations
This document serves as a structured reference for API field definitions and their implementations. Some fields (e.g., `events`, `alerts`, `status` details) may require further exploration depending on use cases.