davi-nfc-agent

API Reference

The NFC Agent uses a two-server architecture:

Server Port Purpose
Device Server 9470 Connects NFC devices (hardware readers, smartphones, browsers)
Client Server 9471 Serves client applications consuming NFC data
CA Bootstrap 9472 Serves TLS certificates for device setup

Device Server API

The Device Server accepts connections from NFC devices that provide tag data.

Connecting

Connect via WebSocket with device mode:

wss://[host]:9470/ws?mode=device

Device Registration

After connecting, register the device:

{
  "type": "registerDevice",
  "payload": {
    "deviceName": "My Device",
    "platform": "ios",
    "appVersion": "1.0.0",
    "capabilities": {
      "canRead": true,
      "canWrite": false,
      "nfcType": "corenfc"
    },
    "metadata": {
      "userAgent": "..."
    }
  }
}

Registration Response:

{
  "type": "registerDeviceResponse",
  "success": true,
  "payload": {
    "deviceID": "dev_abc123",
    "serverInfo": {
      "version": "1.0.0",
      "supportedNFC": ["ndef", "mifare"]
    }
  }
}

Messages from Device

Tag Scanned

Send when a tag is detected:

{
  "type": "tagScanned",
  "payload": {
    "deviceID": "dev_abc123",
    "uid": "04A1B2C3D4E5F6",
    "technology": "ISO14443A",
    "type": "MIFARE Classic 1K",
    "scannedAt": "2024-10-06T12:34:56Z",
    "ndefMessage": {
      "records": [
        {
          "recordType": "text",
          "content": "Hello, NFC!",
          "language": "en"
        }
      ]
    }
  }
}

Tag Removed

Send when a tag leaves the reader:

{
  "type": "tagRemoved",
  "payload": {
    "deviceID": "dev_abc123",
    "uid": "04A1B2C3D4E5F6",
    "removedAt": "2024-10-06T12:35:00Z"
  }
}

Device Heartbeat

Keep connection alive:

{
  "type": "deviceHeartbeat",
  "payload": {
    "deviceID": "dev_abc123",
    "timestamp": "2024-10-06T12:35:30Z"
  }
}

Write Response

Respond to a write request from the server:

{
  "type": "deviceWriteResponse",
  "payload": {
    "requestID": "req_xyz789",
    "success": true,
    "error": ""
  }
}

Messages to Device

Write Request

Server requests the device to write data to a tag:

{
  "type": "deviceWriteRequest",
  "payload": {
    "requestID": "req_xyz789",
    "deviceID": "dev_abc123",
    "ndefMessage": {
      "records": [
        {
          "type": "text",
          "content": "Hello!",
          "language": "en"
        }
      ]
    }
  }
}

mDNS Discovery

The Device Server advertises via mDNS/Bonjour:

Devices can discover the agent on the local network without knowing the IP address.


Client Server API

The Client Server provides NFC data to client applications.

Connecting

Connect via WebSocket:

const ws = new WebSocket('ws://localhost:9471/ws');

With API secret:

const ws = new WebSocket('ws://localhost:9471/ws?secret=your-secret');

Session Behavior

Messages from Server

Device Status

{
  "type": "deviceStatus",
  "payload": {
    "connected": true,
    "message": "Device connected",
    "cardPresent": false
  }
}

Tag Data

When a card is detected and read:

{
  "type": "tagData",
  "payload": {
    "uid": "04A1B2C3D4E5F6",
    "type": "MIFARE Classic 1K",
    "technology": "ISO14443A",
    "scannedAt": "2024-10-06T12:34:56Z",
    "message": {
      "type": "ndef",
      "records": [
        {
          "tnf": 1,
          "type": "T",
          "text": "Hello, NFC!",
          "payload": [72, 101, 108, 108, 111]
        }
      ]
    },
    "text": "Hello, NFC!",
    "err": null
  }
}

Payload Fields:

Field Description
uid Card unique identifier (hex string)
type Card type: MIFARE Classic 1K, MIFARE Classic 4K, MIFARE DESFire, MIFARE Ultralight, ISO14443-4 Type 4A (experimental)
technology NFC technology standard (ISO14443A, ISO14443B, etc.)
scannedAt ISO 8601 timestamp
message Structured NDEF message data
text Quick access to first text record
err Error message or null on success

NDEF Message Structure:

{
  "type": "ndef",
  "records": [
    {
      "tnf": 1,
      "type": "T",
      "text": "Decoded text",
      "language": "en",
      "payload": [...]
    }
  ]
}

Messages to Server

All client messages support an optional id field for request/response correlation.

Write Request

Write NDEF data to a card (complete overwrite):

{
  "id": "req_1",
  "type": "writeRequest",
  "payload": {
    "records": [
      {
        "type": "text",
        "content": "Hello, NFC!",
        "language": "en"
      }
    ]
  }
}

Multiple records:

{
  "id": "req_2",
  "type": "writeRequest",
  "payload": {
    "records": [
      {
        "type": "text",
        "content": "Hello, NFC!",
        "language": "en"
      },
      {
        "type": "uri",
        "content": "https://example.com"
      }
    ]
  }
}

Record Fields:

Field Type Required Description
type string Yes text or uri
content string Yes Text or URI content
language string No ISO language code (default: en)

Write Response

Success:

{
  "id": "req_1",
  "type": "writeResponse",
  "success": true,
  "payload": {
    "message": "Write operation completed successfully"
  }
}

Error:

{
  "id": "req_1",
  "type": "error",
  "success": false,
  "error": "Write failed: card removed",
  "payload": {
    "code": "WRITE_FAILED"
  }
}

Append Pattern

To append records, use read-modify-write:

// 1. Read current tag data
const currentData = await client.getLastTag();

// 2. Extract existing records
const existingRecords = currentData.message.records.map(r => ({
  type: r.type === 'T' ? 'text' : 'uri',
  content: r.text || r.uri,
  language: r.language || 'en'
}));

// 3. Write back with new record appended
socket.send(JSON.stringify({
  type: 'writeRequest',
  payload: {
    records: [...existingRecords, { type: 'text', content: 'New record' }]
  }
}));

REST API

Base URL: http://localhost:9471/api/v1

Health Check

GET /api/v1/health

curl http://localhost:9471/api/v1/health

Response:

{
  "status": "ok"
}

TLS & Certificates

The agent uses auto-generated TLS certificates for secure WebSocket connections.

CA Bootstrap Server

A bootstrap server runs on port 9472 to help devices trust the agent’s certificate:

  1. Open http://[agent-ip]:9472 in a browser
  2. Download the CA certificate
  3. Install on your device

Installing the CA Certificate

iOS:

Android:

Browsers:


Error Codes

Code Description
WRITE_FAILED Write operation failed
NO_CARD No card present on reader
READ_FAILED Failed to read card data
SESSION_LOCKED Another client holds the session
INVALID_REQUEST Malformed request