View on GitHub

easitrace

« Back to Contents

Movement Services | BCMS

Back to Services

Overview

The British Cattle Movement Service (BCMS) is England’s official livestock movement reporting system for cattle. It provides a comprehensive suite of capabilities for managing cattle movements, registrations (births), and health records.

Service ID: 6a341eb4-828a-472f-afef-5566671738a0
Service Tag: BCMS
Supported Countries: England, Wales
Supported Species: Cattle (Bos taurus)
Property Type: Farm
Property Identifier Format: CPH (County/Parish/Holding)


Transaction Types & Capabilities

BCMS implements six primary transaction types with full lifecycle support (Pack, Validate, Send, Poll, Parse):

Capability Code Type Description Polling
Movement On MOV-ON Movement Record cattle moving onto a property Polled (POLL-MOV)
Movement Off MOV-OFF Movement Record cattle moving off a property Polled (POLL-MOV)
Register Animals REG Registration Register cattle births/tags at birth location Polled (POLL-REG)
Record Death DTH Health Record animal death at holding location Polled (POLL-DTH)
Animals on Property GET-ANM Query Get list of cattle currently at a property Real-time
Animal Details ANM-DET Query Get detailed records for specific animals Real-time

Field Keys Architecture

BCMS uses a two-layer field key system for maximum flexibility:

Generic Field Keys (MPaaS.MovementServices.Fields.FieldKeys)

Generic keys apply across all movement services and represent standard livestock movement data:

// Movement context
Movement.MoveDate              // Date of movement (YYYY-MM-DD)
Movement.ConfirmationNo        // Confirmation number
Movement.ExpectedCount         // Expected animal count

// Departure location
Departure.Identifier           // Source property CPH
Departure.Date                 // Departure date
Departure.Country              // Country code
Departure.FirstName            // Contact first name
Departure.LastName             // Contact last name
Departure.PhoneNumber          // Contact phone
Departure.Latitude/Longitude   // Geographic coordinates

// Destination location
Destination.Identifier         // Destination property CPH
Destination.ArrivalDate        // Expected arrival date
Destination.Country            // Destination country
Destination.FirstName          // Recipient first name
Destination.LastName           // Recipient last name
Destination.PhoneNumber        // Recipient phone
Destination.Latitude/Longitude // Geographic coordinates

// Haulier/Transport
Haulier.CompanyName            // Transport company
Haulier.VehicleRegistration    // Vehicle registration
Haulier.DriverName             // Driver name
Haulier.Signature              // Signature string
Haulier.SignatureDate          // Signature date

// Death & Stillbirth
Death.DisposalManner           // Disposal method code
Death.DisposalPlace            // Disposal location
Death.IsSlaughter              // Boolean flag

// Registration/Birth
Register.BirthPropertyIdentifier    // Birth property CPH
Register.BirthPropertyPostalIdentifier // Postal address CPH
Register.Colour                // Animal colour description
Register.ProductionType        // Type code
Register.NMRCode               // NMR identification code

// Animals on Property
GetAnimals.OrderBy             // Sort order for results
GetAnimals.IncludeSubHoldings  // Include sub-locations flag

Specific Field Keys (MPaaS.MovementServices.BCMS.FieldKeys)

Service-specific keys override generic ones with BCMS-specific identifiers:

// BCMS-specific field keys (all with "BCMS." prefix)
BCMS.Movement.Location              // CPH identifier for any movement
BCMS.Movement.ReferenceNumber       // External reference (max 10 chars)
BCMS.Register.BirthLocation         // CPH for birth registration
BCMS.Register.PostalLocation        // Postal address CPH with sub-location
BCMS.AnimalsOnHolding.Location      // Query target CPH
BCMS.Death.Location                 // CPH where death occurred

Key Override Mapping

Transaction Generic Key Specific Key Implementation
Move On Destination.Identifier BCMS.Movement.Location MoveOnFieldKeys.MoveOnLocation
Move Off Departure.Identifier BCMS.Movement.Location MoveOffFieldKeys.MoveOffLocation
Register Register.BirthPropertyIdentifier BCMS.Register.BirthLocation RegisterFieldKeys.BirthLocation
Register Register.BirthPropertyPostalIdentifier BCMS.Register.PostalLocation RegisterFieldKeys.BirthPostalLocation
Death Death.DeathLocation BCMS.Death.Location DeathFieldKeys.DeathLocation
Animals Query GetAnimals.IncludeSubHoldings BCMS.AnimalsOnHolding.Location Service-specific

Movement On Transaction

Capability: MOV-ON Polling: Yes (POLL-MOV) Animals: Single or batch

Record cattle moving onto a property (arrival event).

Field Requirements

Generic Key Specific Key Type Format Required Example
Departure.Identifier - String CPH cc/ppp/hhhh 11/222/3333
Destination.Identifier BCMS.Movement.Location String CPH cc/ppp/hhhh[-XX] 11/222/3333
Movement.MoveDate BCMS.Movement.MovementDate Date YYYY-MM-DD 2024-01-15
Movement.ConfirmationNo BCMS.Movement.ReferenceNumber String Max 10 chars REF123456
Movement.ExpectedCount - Integer Positive number 50
Destination.Country - String 2-char code GB
Haulier.CompanyName - String Max 255 Transport Ltd
Haulier.VehicleRegistration - String Max 20 AB54CDE
Haulier.DriverName - String Max 255 John Smith

Field Values Collection

Class: MoveOnTransactionFieldValueCollection

Provides strongly-typed access to movement data:

public Cph MoveOnLocation { get; }           // Destination CPH (with optional sub-location)
public string AnimalEtag { get; }            // Individual animal ear tag
public string AnimalEid { get; }             // Electronic ID
public DateTimeOffset? MoveDate { get; }     // Movement date-time
public int? RowNumber { get; }               // Batch sequence number

XML Structure (Request)

<RegMovs xmlns="http://defra.bcms.ctws/register_movements_request"
         SchemaVersion="1.0"
         ProgramName="StockTrace.Linx"
         ProgramVersion="1.0"
         RequestTimeStamp="2024-01-15T10:30:00Z">
  <Authentication>
    <SIS_User Id="1234567" SourceEmail="user@example.com" />
  </Authentication>
  <Moves TxnId="Linx{UUID}">
    <Mov RowNum="1" 
         Etg="UK0244220" 
         EId="12345678" 
         Loc="11/222/3333" 
         MType="on" 
         MDate="2024-01-15" />
  </Moves>
</RegMovs>

Authentication Methods


Movement Off Transaction

Capability: MOV-OFF Polling: Yes (POLL-MOV) Animals: Single or batch

Record cattle leaving a property (departure event).

Field Requirements

Generic Key Specific Key Type Format Required Example
Departure.Identifier BCMS.Movement.Location String CPH cc/ppp/hhhh[-XX] 11/222/3333
Destination.Identifier - String CPH cc/ppp/hhhh 22/333/4444
Movement.MoveDate BCMS.Movement.MovementDate Date YYYY-MM-DD 2024-01-15
Movement.ConfirmationNo BCMS.Movement.ReferenceNumber String Max 10 chars REF123456
Movement.ExpectedCount - Integer Positive number 50
Departure.Country - String 2-char code GB
Haulier.CompanyName - String Max 255 Transport Ltd
Haulier.VehicleRegistration - String Max 20 AB54CDE
Haulier.DriverName - String Max 255 Jane Doe

Field Values Collection

Class: MoveOffTransactionFieldValueCollection

public Cph MoveOffLocation { get; }          // Departure CPH
public string AnimalEtag { get; }            // Ear tag
public string AnimalEid { get; }             // Electronic ID
public DateTimeOffset? MoveDate { get; }     // Departure date
public int? RowNumber { get; }               // Batch sequence

XML Structure (Request)

<RegMovs xmlns="http://defra.bcms.ctws/register_movements_request"
         SchemaVersion="1.0"
         ProgramName="StockTrace.Linx"
         ProgramVersion="1.0"
         RequestTimeStamp="2024-01-15T14:45:00Z">
  <Authentication>
    <SIS_User Id="1234567" SourceEmail="user@example.com" />
  </Authentication>
  <Moves TxnId="Linx{UUID}">
    <Mov RowNum="1" 
         Etg="UK0244220" 
         EId="12345678" 
         Loc="11/222/3333" 
         MType="off" 
         MDate="2024-01-15" />
  </Moves>
</RegMovs>

Register Animals Transaction

Capability: REG Polling: Yes (POLL-REG) Animals: Single or batch

Register new cattle births or animals at their birth location.

Field Requirements

Generic Key Specific Key Type Format Required Example
Register.BirthPropertyIdentifier BCMS.Register.BirthLocation String CPH cc/ppp/hhhh 11/222/3333
Register.BirthPropertyPostalIdentifier BCMS.Register.PostalLocation String CPH cc/ppp/hhhh[-XX] 11/222/3333-01
Register.Colour - String Colour description Black and White
Register.ProductionType - String Type code beef or dairy
Register.NMRCode - String NMR identifier NMR123456
Movement.MoveDate - Date YYYY-MM-DD 2024-01-15
Movement.ExpectedCount - Integer Positive 1

Field Values Collection

Class: RegisterTransactionFieldValueCollection

public Cph BirthLocation { get; }            // Birth property CPH
public Cph PostalLocation { get; }           // Postal address CPH with sub-location
public string AnimalEtag { get; }            // New ear tag assigned
public string AnimalEid { get; }             // Electronic ID
public string Colour { get; }                // Animal colour
public string ProductionType { get; }        // Production type code
public DateTimeOffset? BirthDate { get; }    // Birth date
public int? RowNumber { get; }               // Batch sequence

XML Structure (Request)

<RegBirths xmlns="http://defra.bcms.ctws/register_births_request"
           SchemaVersion="1.0"
           ProgramName="StockTrace.Linx"
           ProgramVersion="1.0"
           RequestTimeStamp="2024-01-15T09:00:00Z">
  <Authentication>
    <SIS_User Id="1234567" SourceEmail="user@example.com" />
  </Authentication>
  <Births TxnId="MPaaS{UUID}">
    <Birth RowNum="1" 
           Etg="UK0244220" 
           BDate="2024-01-14" 
           Loc="11/222/3333" 
           Colour="Black"
           ProductionType="dairy" />
  </Births>
</RegBirths>

Record Death Transaction

Capability: DTH Polling: Yes (POLL-DTH) Animals: Single or batch

Record the death of cattle at a holding location.

Field Requirements

Generic Key Specific Key Type Format Required Example
Death.DeathLocation BCMS.Death.Location String CPH cc/ppp/hhhh 11/222/3333
Death.Date - Date YYYY-MM-DD 2024-01-15
Death.DisposalManner - String Disposal code burial
Death.DisposalPlace - String Location description Farm premises
Death.IsSlaughter - Boolean true/false false
Movement.ExpectedCount - Integer Positive 1

Field Values Collection

Class: DeathTransactionFieldValueCollection

public Cph DeathLocation { get; }            // Death location CPH
public string AnimalEtag { get; }            // Ear tag of deceased
public string AnimalEid { get; }             // Electronic ID
public DateTimeOffset? DeathDate { get; }    // Date of death
public string DisposalManner { get; }        // Disposal method
public string DisposalPlace { get; }         // Disposal location
public bool? IsSlaughter { get; }            // Slaughter flag
public int? RowNumber { get; }               // Batch sequence

XML Structure (Request)

<RegMovs xmlns="http://defra.bcms.ctws/register_movements_request"
         SchemaVersion="1.0"
         ProgramName="StockTrace.Linx"
         ProgramVersion="1.0"
         RequestTimeStamp="2024-01-15T16:20:00Z">
  <Authentication>
    <SIS_User Id="1234567" SourceEmail="user@example.com" />
  </Authentication>
  <Moves TxnId="Linx{UUID}">
    <Mov RowNum="1" 
         Etg="UK0244220" 
         Loc="11/222/3333" 
         MType="death" 
         MDate="2024-01-15" />
  </Moves>
</RegMovs>

Get Animals on Property Query

Capability: GET-ANM Polling: No (Real-time) Type: Query

Query current cattle inventory at a property.

Field Requirements

Generic Key Specific Key Type Format Required Example
Property.Identifier BCMS.AnimalsOnHolding.Location String CPH cc/ppp/hhhh 11/222/3333
GetAnimals.IncludeSubHoldings - Boolean true/false false
GetAnimals.OrderBy - String Sort field ETag

Response Structure

Class: AnimalQueryResponse

public List<Animal> Animals { get; }         // List of animals at property
public int TotalCount { get; }               // Total animal count
public DateTime QueryDate { get; }           // Query execution date

public class Animal
{
    public string ETag { get; set; }         // Ear tag
    public string EId { get; set; }          // Electronic ID
    public string Colour { get; set; }       // Animal colour
    public string Sex { get; set; }          // M/F
    public DateTime? DateOfBirth { get; set; }
    public string Status { get; set; }       // Current status
}

XML Structure (Request)

<GetHolding xmlns="http://defra.bcms.ctws/get_cattle_on_holding_request"
            SchemaVersion="1.0"
            ProgramName="StockTrace.Linx"
            ProgramVersion="1.0"
            RequestTimeStamp="2024-01-15T11:00:00Z">
  <Authentication>
    <SIS_User Id="1234567" SourceEmail="user@example.com" />
  </Authentication>
  <Holding>
    <Loc>11/222/3333</Loc>
    <SLoc>01</SLoc>
  </Holding>
</GetHolding>

Get Animal Details Query

Capability: ANM-DET Polling: No (Real-time) Type: Query

Get detailed movement and health records for specific animals.

Field Requirements

Generic Key Specific Key Type Format Required Example
Property.Identifier - String CPH 11/222/3333
SerialNumber - String Ear tag or EID UK0244220

Response Structure

Class: AnimalDetailsResponse

public Animal AnimalRecord { get; }          // Complete animal profile
public List<MovementHistory> Movements { get; }  // Movement history
public List<HealthRecord> HealthRecords { get; } // Death/disease records

public class MovementHistory
{
    public DateTime Date { get; set; }
    public string FromLocation { get; set; }
    public string ToLocation { get; set; }
    public string HaulierDetails { get; set; }
}

public class HealthRecord
{
    public DateTime Date { get; set; }
    public string Type { get; set; }         // death, disease, etc.
    public string Details { get; set; }
}

XML Structure (Request)

<GetAnimalDetails xmlns="http://defra.bcms.ctws/get_animal_details_request"
                  SchemaVersion="1.0"
                  ProgramName="StockTrace.Linx"
                  ProgramVersion="1.0"
                  RequestTimeStamp="2024-01-15T12:30:00Z">
  <Authentication>
    <SIS_User Id="1234567" SourceEmail="user@example.com" />
  </Authentication>
  <Animal>
    <SerialNumber>UK0244220</SerialNumber>
    <Holding>11/222/3333</Holding>
  </Animal>
</GetAnimalDetails>

Species Support

BCMS exclusively supports cattle operations:

Species Code ID Supported Notes
Cattle CATTLE 32fc13b2-f8a3-47b9-8941-ed52df072265 ✓ Yes All capabilities

Property Identifier Format: CPH

County/Parish/Holding (CPH) is the standard UK farm identifier used by BCMS.

Format Specification

Standard CPH: CC/PPP/HHHH

CPH with Sub-location: CC/PPP/HHHH-XX

Examples

Standard:           11/222/3333
With sub-location:  11/222/3333-01
With letter suffix: 11/222/3333-A5

Validation Rules

// Regex patterns (from Cph.cs)
County:       ^[0-9]{2}$        // Exactly 2 digits
Parish:       ^[0-9]{3}$        // Exactly 3 digits
Holding:      ^[0-9]{4}$        // Exactly 4 digits
SubLocation:  ^[0-9A-Za-z]{2}$  // Exactly 2 alphanumeric

Implementation

Class: Cph (MPaaS.MovementServices.Models)

var cph = new Cph("11/222/3333");
var cphWithSub = new Cph("11/222/3333-01");

// Access parsed components
string county = cph.County;              // "11"
string parish = cph.Parish;              // "222"
string holding = cph.Holding;            // "3333"
string subLocation = cph.SubLocation;    // null or "01"
string formatted = cph.CPH;              // "11/222/3333"
string full = cph.ToString();            // "11/222/3333" or "11/222/3333-01"

// Safe parsing
if (Cph.TryParse(propertyId, out var parsed))
{
    // Use parsed CPH
}

Authentication

BCMS supports two authentication schemes determined by the username format:

1. SIS (Standard Information Service)

Detection: Numeric username only Credentials:

XML Element:

<SIS_User Id="1234567" SourceEmail="user@farm.co.uk" />

2. CTS (Cattle Tracing System)

Detection: Username contains non-numeric characters or passes WsInfo.IsCTSAuth() Credentials:

XML Element:

<CTSOL_User Usr="CTSUsername" Pwd="CTSPassword" />

Service Provider Credentials

Required for all requests:

public RequiredCredentials RequiredCredentials =>
    RequiredCredentials.ServiceProviderUsername |    // BCMS web service user
    RequiredCredentials.ServiceProviderPassword |    // BCMS web service password
    RequiredCredentials.ProgramName |                // Your application name
    RequiredCredentials.ProgramVersion |             // Your application version
    RequiredCredentials.PropertyUsername |           // Property/farm user ID
    RequiredCredentials.PropertyPassword;            // Property user password

Credential Validation

Class: UserCredentialValidator

Validates property credentials by executing a test GetAnimalsOnProperty query:

public bool Validate(string username, ref string password, 
    ServiceProviderAuthentication serviceProviderAuth)
{
    // Sends test query to BCMS
    // Validates authentication against known error codes:
    // - CTWS800: Invalid username/password
    // - CTWS801: Invalid credentials
    // - CTWS805: User not authorized
    
    return CheckValidReturn(response, authentication);
}

Request/Response Flow

Standard Polling Request (Movement On/Off/Death)

  1. Pack: Convert transaction to XML with authentication
  2. Validate: Check XSD compliance and required fields
  3. Send: POST XML to BCMS web service
  4. Poll: Query result status with transaction ID
  5. Parse: Extract success/error details from response

Query Request (Animals on Property/Details)

  1. Pack: Convert query parameters to XML
  2. Validate: Check CPH format and authentication
  3. Send: POST XML to BCMS web service
  4. Parse: Deserialize animal list/details directly

Error Handling

Class: BcmsErrorMapper

Maps BCMS-specific error codes to standard error responses:

// Example mappings
"CTWS800"  UserCredentialsInvalid
"CTWS801"  ServiceCredentialsInvalid
"CTWS805"  UserNotAuthorized
SystemException_Structure  Technical error with code and message

Service Registry

File: BcmsMovementServiceRegistry.cs

Registers all BCMS capabilities with dependency injection:

// Polled capabilities
serviceCollection
    .AddCapability<BcmsMovementService, IMoveOnCapable>()
    .WithPacker<PackMoveOn>()
    .WithParser<ParseMoveOn>()
    .WithValidator<ValidateMoveOn>()
    .WithPoller<PollMoveOn>()
    .WithSender<PolledRequestSender<IMoveOnCapable>>()
    .Build();

// Real-time capabilities
serviceCollection
    .AddCapability<BcmsMovementService, IAnimalsOnPropertyCapable>()
    .WithPacker<PackAnimalQuery>()
    .WithParser<ParseAnimalQuery>()
    .WithValidator<ValidateAnimalQuery>()
    .WithSender<SendAnimalQuery>()
    .Build();

// Configuration services
serviceCollection.AddScoped<IBCMSSettings, BCMSSettings>();
serviceCollection.AddScoped<IPropertyValidator<BcmsMovementService>, PropertyValidator>();
serviceCollection.AddScoped<IUserCredentialValidator<BcmsMovementService>, UserCredentialValidator>();
serviceCollection.AddScoped<IXSDValidator, XSDValidator>();

Configuration

Class: BCMSSettingsServiceConfiguration

Configuration keys in appsettings.json:

{
  "BCMS": {
    "WebServiceURL": "https://service.bcms.defra.gov.uk/",
    "ServiceName": "BCMS",
    "MaxAttemptCount": 3,
    "MaxTimeoutSeconds": 300,
    "PollIntervalSeconds": 5
  }
}

Access:

IBCMSSettings settings = serviceProvider.GetRequiredService<IBCMSSettings>();
string wsUrl = settings.WebServiceUrl;
int maxAttempts = settings.MaxAttemptCount;

Testing Resources

Complete test suites available in MPaaS.MovementServices.Tests/BCMS/:

Test Resources:

Resources/BCMS/
  ├── MoveOn/PackMoveOnResult.xml
  ├── MoveOff/PackMoveOffResult.xml
  ├── Death/PackDeathResult.xml
  ├── Register/PackRegisterResult.xml
  ├── AnimalQuery/
  │   ├── PackCTSUserExpectedResponse.xml
  │   ├── PackNonCTSUserExpectedResponse.xml
  │   ├── ParseResponseSuccess.xml
  │   └── ParseResponseFailed.xml
  └── AnimalDetails/
      ├── PackAnimalDetailsRequestCTSAuthValid.xml
      ├── PackAnimalDetailsRequestSISAuthValid.xml
      └── ParseAnimalDetailsResponseWithAnimals.xml

Implementation Guide

Basic Movement On Request

var transaction = new Transaction
{
    PropertyIdentifier = "11/222/3333",      // Source property
    SpeciesCode = Species.Cattle.Value,
    Type = ServiceCapability.MoveOn.Code,
    Fields = new Dictionary<IFieldKey, string>
    {
        { MoveOnFieldKeys.MoveOnLocation, "11/222/3334" },  // Destination
        { FieldKeys.Movement.MoveDate, "2024-01-15" },
        { FieldKeys.Movement.ExpectedCount, "50" }
    },
    Animals = new List<Animal>
    {
        new() { SerialNumber = "UK0244220", Identifier = "UK0244220" },
        // ... additional animals
    }
};

var auth = new Authentication
{
    PropertyAuth = new PropertyAuthentication
    {
        Username = "1234567",                 // SIS user ID
        Password = "user@farm.co.uk"         // SIS email
    },
    ServiceProviderAuth = new ServiceProviderAuthentication
    {
        ProgramName = "MyApp",
        ProgramVersion = "1.0",
        SchemaVersion = "1.0"
    }
};

var result = await movementService.Send(transaction, auth);

Query Animals on Property

var query = new Transaction
{
    PropertyIdentifier = "11/222/3333",
    SpeciesCode = Species.Cattle.Value,
    Type = ServiceCapability.GetAnimalsOnProperty.Code
};

var response = await movementService.Send(query, auth);
// Response.Result contains animal list

Limitations & Constraints


References


Last Updated: 2024 Service Version: 1.0 Schema Version: 1.0