SDK

The [R]DP SDKs are client packages for applications integrating with [R]DP platform APIs.

They provide generated service clients and shared behavior for transport, authentication configuration, logging, and optional timeouts.

v2026.21.1
Go
Java
Python
TypeScript

Getting Started

Download the SDK package for your implementation language, choose the release that matches your target environment, install it with the normal tooling for that language, then use the generated client to call platform services.

The SDKs read RDP_SERVER_URL, RDP_SERVER_PORT, TLS_SKIP_VERIFY, RDP_CLIENT_ID, RDP_CLIENT_SECRET, and RDP_API_KEY from their standard configuration loaders. The examples below are the same snippets used by the WDM Object and Action guides. For the full operation set, see Object and Action.

Publish an Object

Use PublishObject to create or update a single Object.

package main

import (
	"context"
	"log"
	"time"

	"connectrpc.com/connect"
	"google.golang.org/protobuf/types/known/timestamppb"

	wdmsdk "github.com/raft-tech/raft-wdm-sdk-go"
	pb "github.com/raft-tech/raft-wdm-sdk-go/gen/raft/wdm/v1"
	svc "github.com/raft-tech/raft-wdm-sdk-go/gen/raft/wdm/v1/service"
)

func main() {
	cfg, err := wdmsdk.LoadConfig()
	if err != nil {
		log.Fatal(err)
	}

	client, err := wdmsdk.NewFromConfig(cfg)
	if err != nil {
		log.Fatal(err)
	}

	updatedAt := time.Now().UTC()
	_, err = client.ObjectService().PublishObject(context.Background(), connect.NewRequest(&svc.PublishObjectRequest{
		Object: &pb.Object{
			Id:     "link16-track-47210",
			Name:   "TRACK-47210",
			Status: pb.ObjectStatus_OBJECT_STATUS_ACTIVE,
			Ttl:    timestamppb.New(updatedAt.Add(5 * time.Minute)),
			Provenance: &pb.ProvenanceRecord{
				Name:      "aegis-radar-07",
				UpdatedAt: timestamppb.New(updatedAt),
			},
		},
	}))
	if err != nil {
		log.Fatal(err)
	}
}
import com.google.protobuf.Timestamp;
import com.raft.wdm.Wdm;
import com.raft.wdm.raft.wdm.v1.Object;
import com.raft.wdm.raft.wdm.v1.ObjectStatus;
import com.raft.wdm.raft.wdm.v1.ProvenanceRecord;
import com.raft.wdm.raft.wdm.v1.service.PublishObjectRequest;
import com.raft.wdm.v1.WdmV1Client;
import java.time.Instant;

public final class PublishObjectExample {
  public static void main(String[] args) {
    var options = Wdm.toOptions(Wdm.loadConfig(null, null));
    var updatedAt = Instant.now();

    try (var client = WdmV1Client.create(options)) {
      var req = PublishObjectRequest.newBuilder()
          .setObject(Object.newBuilder()
              .setId("link16-track-47210")
              .setName("TRACK-47210")
              .setStatus(ObjectStatus.OBJECT_STATUS_ACTIVE)
              .setTtl(timestamp(updatedAt.plusSeconds(300)))
              .setProvenance(ProvenanceRecord.newBuilder()
                  .setName("aegis-radar-07")
                  .setUpdatedAt(timestamp(updatedAt))))
          .build();

      client.getObjectServiceBlocking()
          .publishObjectBlocking(req)
          .execute();
    }
  }

  private static Timestamp timestamp(Instant instant) {
    return Timestamp.newBuilder()
        .setSeconds(instant.getEpochSecond())
        .setNanos(instant.getNano())
        .build();
  }
}
import asyncio
from datetime import datetime, timedelta, timezone

from google.protobuf.timestamp_pb2 import Timestamp
from raft.wdm.v1 import object_pb2
from raft.wdm.v1 import common_pb2
from raft.wdm.v1.service import object_service_pb2

import raft_wdm_sdk


def timestamp(dt: datetime) -> Timestamp:
    value = Timestamp()
    value.FromDatetime(dt)
    return value


async def main() -> None:
    updated_at = datetime.now(timezone.utc)

    async with raft_wdm_sdk.Client.from_config(raft_wdm_sdk.load_config()) as client:
        await client.object_service.publish_object(
            object_service_pb2.PublishObjectRequest(
                object=object_pb2.Object(
                    id="link16-track-47210",
                    name="TRACK-47210",
                    status=object_pb2.OBJECT_STATUS_ACTIVE,
                    ttl=timestamp(updated_at + timedelta(minutes=5)),
                    provenance=common_pb2.ProvenanceRecord(
                        name="aegis-radar-07",
                        updated_at=timestamp(updated_at),
                    ),
                ),
            ),
        )


asyncio.run(main())
import { create } from "@bufbuild/protobuf";
import { timestampFromDate } from "@bufbuild/protobuf/wkt";
import { createClient, fromNodeConfig, loadConfig } from "@raft-tech/raft-wdm-sdk-typescript";
import { ObjectStatus } from "@raft-tech/raft-wdm-sdk-typescript/gen/raft/wdm/v1/object_pb.js";
import { PublishObjectRequestSchema } from "@raft-tech/raft-wdm-sdk-typescript/gen/raft/wdm/v1/service/object_service_pb.js";

const client = createClient(...fromNodeConfig(loadConfig()));

const updatedAt = new Date();

await client.objectService.publishObject(
  create(PublishObjectRequestSchema, {
    object: {
      id: "link16-track-47210",
      name: "TRACK-47210",
      status: ObjectStatus.OBJECT_STATUS_ACTIVE,
      ttl: timestampFromDate(new Date(updatedAt.getTime() + 5 * 60 * 1000)),
      provenance: {
        name: "aegis-radar-07",
        updatedAt: timestampFromDate(updatedAt),
      },
    },
  }),
);
curl -X POST "${RDP_SERVER_URL}/api/v1/wdm/objects" \
  -H "X-API-KEY: ${RDP_API_KEY}" \
  -H "Content-Type: application/json" \
  --json @- <<JSON
{
  "object": {
    "id": "link16-track-47210",
    "name": "TRACK-47210",
    "status": "OBJECT_STATUS_ACTIVE",
    "ttl": "2026-05-27T21:36:04Z",
    "provenance": {
      "name": "aegis-radar-07",
      "updatedAt": "2026-05-27T21:31:04Z"
    }
  }
}
JSON

Search Objects

Use SearchObjects to retrieve a paginated snapshot of Objects that match your filters.

package main

import (
	"connectrpc.com/connect"
	"context"
	"log"

	wdmsdk "github.com/raft-tech/raft-wdm-sdk-go"
	pb "github.com/raft-tech/raft-wdm-sdk-go/gen/raft/wdm/v1"
	svc "github.com/raft-tech/raft-wdm-sdk-go/gen/raft/wdm/v1/service"
)

func main() {
	cfg, err := wdmsdk.LoadConfig()
	if err != nil {
		log.Fatal(err)
	}

	client, err := wdmsdk.NewFromConfig(cfg)
	if err != nil {
		log.Fatal(err)
	}

	resp, err := client.ObjectService().SearchObjects(context.Background(), connect.NewRequest(&svc.SearchObjectsRequest{
		Query: &svc.ObjectQuery{
			Statuses:     []pb.ObjectStatus{pb.ObjectStatus_OBJECT_STATUS_ACTIVE},
			Affiliations: []pb.Affiliation{pb.Affiliation_AFFILIATION_FRIEND},
		},
		PageSize: 100,
	}))
	if err != nil {
		log.Fatal(err)
	}

	for _, obj := range resp.Msg.GetObjects() {
		log.Printf("found object: %s %s", obj.GetId(), obj.GetName())
	}
}
import com.raft.wdm.Wdm;
import com.raft.wdm.raft.wdm.v1.Affiliation;
import com.raft.wdm.raft.wdm.v1.ObjectStatus;
import com.raft.wdm.raft.wdm.v1.service.ObjectQuery;
import com.raft.wdm.raft.wdm.v1.service.SearchObjectsRequest;
import com.raft.wdm.v1.WdmV1Client;

public final class SearchObjectsExample {
  public static void main(String[] args) {
    var options = Wdm.toOptions(Wdm.loadConfig(null, null));

    try (var client = WdmV1Client.create(options)) {
      var req = SearchObjectsRequest.newBuilder()
          .setQuery(ObjectQuery.newBuilder()
              .addStatuses(ObjectStatus.OBJECT_STATUS_ACTIVE)
              .addAffiliations(Affiliation.AFFILIATION_FRIEND))
          .setPageSize(100)
          .build();

      client.getObjectServiceBlocking()
          .searchObjectsBlocking(req)
          .execute();
    }
  }
}
import asyncio

from raft.wdm.v1 import assessment_pb2
from raft.wdm.v1 import object_pb2
from raft.wdm.v1.service import object_service_pb2
from raft.wdm.v1.service import query_pb2

import raft_wdm_sdk


async def main() -> None:
    async with raft_wdm_sdk.Client.from_config(raft_wdm_sdk.load_config()) as client:
        response = await client.object_service.search_objects(
            object_service_pb2.SearchObjectsRequest(
                query=query_pb2.ObjectQuery(
                    statuses=[object_pb2.OBJECT_STATUS_ACTIVE],
                    affiliations=[assessment_pb2.AFFILIATION_FRIEND],
                ),
                page_size=100,
            ),
        )

        for obj in response.objects:
            print(f"found object: {obj.id} {obj.name}")


asyncio.run(main())
import { create } from "@bufbuild/protobuf";
import { createClient, fromNodeConfig, loadConfig } from "@raft-tech/raft-wdm-sdk-typescript";
import { Affiliation } from "@raft-tech/raft-wdm-sdk-typescript/gen/raft/wdm/v1/assessment_pb.js";
import { ObjectStatus } from "@raft-tech/raft-wdm-sdk-typescript/gen/raft/wdm/v1/object_pb.js";
import { SearchObjectsRequestSchema } from "@raft-tech/raft-wdm-sdk-typescript/gen/raft/wdm/v1/service/object_service_pb.js";

const client = createClient(...fromNodeConfig(loadConfig()));

const response = await client.objectService.searchObjects(
  create(SearchObjectsRequestSchema, {
    query: {
      statuses: [ObjectStatus.OBJECT_STATUS_ACTIVE],
      affiliations: [Affiliation.AFFILIATION_FRIEND],
    },
    pageSize: 100,
  }),
);

for (const object of response.objects) {
  console.log(`found object: ${object.id} ${object.name}`);
}
curl -X POST "${RDP_SERVER_URL}/api/v1/wdm/objects/search" \
  -H "X-API-KEY: ${RDP_API_KEY}" \
  -H "Content-Type: application/json" \
  --json @- <<JSON
{
  "query": {
    "statuses": ["OBJECT_STATUS_ACTIVE"],
    "affiliations": ["AFFILIATION_FRIEND"]
  },
  "pageSize": 100
}
JSON

Create an Action

Use CreateAction to create a new Action with its routing, intent, priority, timing, and related Objects.

package main

import (
	"context"
	"log"
	"time"

	"connectrpc.com/connect"
	"google.golang.org/protobuf/types/known/timestamppb"

	wdmsdk "github.com/raft-tech/raft-wdm-sdk-go"
	pb "github.com/raft-tech/raft-wdm-sdk-go/gen/raft/wdm/v1"
	svc "github.com/raft-tech/raft-wdm-sdk-go/gen/raft/wdm/v1/service"
)

func main() {
	cfg, err := wdmsdk.LoadConfig()
	if err != nil {
		log.Fatal(err)
	}

	client, err := wdmsdk.NewFromConfig(cfg)
	if err != nil {
		log.Fatal(err)
	}

	updatedAt := time.Now().UTC()
	_, err = client.ActionService().CreateAction(context.Background(), connect.NewRequest(&svc.CreateActionRequest{
		Action: &pb.Action{
			Id:       "isr-collect-alpha",
			Name:     "ISR Collection Alpha",
			Type:     "isr_collection",
			Scope:    pb.ActionScope_ACTION_SCOPE_TASK,
			State:    pb.ActionState_ACTION_STATE_ASSIGNED,
			Priority: pb.ActionPriority_ACTION_PRIORITY_HIGH,
			RequestedBy: &pb.Principal{
				Id:   "ops-cell-alpha",
				Type: pb.PrincipalType_PRINCIPAL_TYPE_USER,
			},
			AssignedTo: &pb.Principal{
				Id:   "uav-shadow-07",
				Type: pb.PrincipalType_PRINCIPAL_TYPE_OBJECT,
			},
			AuthorizedBy: &pb.Principal{
				Id:   "s2-battle-captain",
				Type: pb.PrincipalType_PRINCIPAL_TYPE_USER,
			},
			Intent: &pb.Intent{
				Purpose:  "Observe NAI 3 before the convoy crosses phase line BLUE",
				Method:   "Maintain a collection orbit with EO/IR coverage",
				EndState: "Report movement or changes near the route",
			},
			ObjectLinks: []*pb.ObjectLink{
				{
					ObjectId: "link16-track-47210",
					Type:     pb.ObjectLinkType_OBJECT_LINK_TYPE_TARGET,
				},
			},
			Provenance: &pb.ProvenanceRecord{
				Name:      "ops-center-01",
				UpdatedAt: timestamppb.New(updatedAt),
			},
		},
	}))
	if err != nil {
		log.Fatal(err)
	}
}
import com.google.protobuf.Timestamp;
import com.raft.wdm.Wdm;
import com.raft.wdm.raft.wdm.v1.Action;
import com.raft.wdm.raft.wdm.v1.ActionPriority;
import com.raft.wdm.raft.wdm.v1.ActionScope;
import com.raft.wdm.raft.wdm.v1.ActionState;
import com.raft.wdm.raft.wdm.v1.Intent;
import com.raft.wdm.raft.wdm.v1.ObjectLink;
import com.raft.wdm.raft.wdm.v1.ObjectLinkType;
import com.raft.wdm.raft.wdm.v1.Principal;
import com.raft.wdm.raft.wdm.v1.PrincipalType;
import com.raft.wdm.raft.wdm.v1.ProvenanceRecord;
import com.raft.wdm.raft.wdm.v1.service.CreateActionRequest;
import com.raft.wdm.v1.WdmV1Client;
import java.time.Instant;

public final class CreateActionExample {
  public static void main(String[] args) {
    var options = Wdm.toOptions(Wdm.loadConfig(null, null));
    var updatedAt = Instant.now();

    try (var client = WdmV1Client.create(options)) {
      var req = CreateActionRequest.newBuilder()
          .setAction(Action.newBuilder()
              .setId("isr-collect-alpha")
              .setName("ISR Collection Alpha")
              .setType("isr_collection")
              .setScope(ActionScope.ACTION_SCOPE_TASK)
              .setState(ActionState.ACTION_STATE_ASSIGNED)
              .setPriority(ActionPriority.ACTION_PRIORITY_HIGH)
              .setRequestedBy(Principal.newBuilder()
                  .setId("ops-cell-alpha")
                  .setType(PrincipalType.PRINCIPAL_TYPE_USER))
              .setAssignedTo(Principal.newBuilder()
                  .setId("uav-shadow-07")
                  .setType(PrincipalType.PRINCIPAL_TYPE_OBJECT))
              .setAuthorizedBy(Principal.newBuilder()
                  .setId("s2-battle-captain")
                  .setType(PrincipalType.PRINCIPAL_TYPE_USER))
              .setIntent(Intent.newBuilder()
                  .setPurpose("Observe NAI 3 before the convoy crosses phase line BLUE")
                  .setMethod("Maintain a collection orbit with EO/IR coverage")
                  .setEndState("Report movement or changes near the route"))
              .addObjectLinks(ObjectLink.newBuilder()
                  .setObjectId("link16-track-47210")
                  .setType(ObjectLinkType.OBJECT_LINK_TYPE_TARGET))
              .setProvenance(ProvenanceRecord.newBuilder()
                  .setName("ops-center-01")
                  .setUpdatedAt(timestamp(updatedAt))))
          .build();

      client.getActionService()
          .createActionBlocking(req)
          .execute();
    }
  }

  private static Timestamp timestamp(Instant instant) {
    return Timestamp.newBuilder()
        .setSeconds(instant.getEpochSecond())
        .setNanos(instant.getNano())
        .build();
  }
}
import asyncio
from datetime import datetime, timezone

from google.protobuf.timestamp_pb2 import Timestamp
from raft.wdm.v1 import action_pb2
from raft.wdm.v1 import common_pb2
from raft.wdm.v1.service import action_service_pb2

import raft_wdm_sdk


def timestamp(dt: datetime) -> Timestamp:
    value = Timestamp()
    value.FromDatetime(dt)
    return value


async def main() -> None:
    updated_at = datetime.now(timezone.utc)

    async with raft_wdm_sdk.Client.from_config(raft_wdm_sdk.load_config()) as client:
        await client.action_service.create_action(
            action_service_pb2.CreateActionRequest(
                action=action_pb2.Action(
                    id="isr-collect-alpha",
                    name="ISR Collection Alpha",
                    type="isr_collection",
                    scope=action_pb2.ACTION_SCOPE_TASK,
                    state=action_pb2.ACTION_STATE_ASSIGNED,
                    priority=action_pb2.ACTION_PRIORITY_HIGH,
                    requested_by=common_pb2.Principal(
                        id="ops-cell-alpha",
                        type=common_pb2.PRINCIPAL_TYPE_USER,
                    ),
                    assigned_to=common_pb2.Principal(
                        id="uav-shadow-07",
                        type=common_pb2.PRINCIPAL_TYPE_OBJECT,
                    ),
                    authorized_by=common_pb2.Principal(
                        id="s2-battle-captain",
                        type=common_pb2.PRINCIPAL_TYPE_USER,
                    ),
                    intent=action_pb2.Intent(
                        purpose="Observe NAI 3 before the convoy crosses phase line BLUE",
                        method="Maintain a collection orbit with EO/IR coverage",
                        end_state="Report movement or changes near the route",
                    ),
                    object_links=[
                        action_pb2.ObjectLink(
                            object_id="link16-track-47210",
                            type=action_pb2.OBJECT_LINK_TYPE_TARGET,
                        ),
                    ],
                    provenance=common_pb2.ProvenanceRecord(
                        name="ops-center-01",
                        updated_at=timestamp(updated_at),
                    ),
                ),
            ),
        )


asyncio.run(main())
import { create } from "@bufbuild/protobuf";
import { timestampFromDate } from "@bufbuild/protobuf/wkt";
import { createClient, fromNodeConfig, loadConfig } from "@raft-tech/raft-wdm-sdk-typescript";
import { PrincipalType } from "@raft-tech/raft-wdm-sdk-typescript/gen/raft/wdm/v1/common_pb.js";
import {
  ActionPriority,
  ActionScope,
  ActionState,
  ObjectLinkType,
} from "@raft-tech/raft-wdm-sdk-typescript/gen/raft/wdm/v1/action_pb.js";
import { CreateActionRequestSchema } from "@raft-tech/raft-wdm-sdk-typescript/gen/raft/wdm/v1/service/action_service_pb.js";

const client = createClient(...fromNodeConfig(loadConfig()));

const updatedAt = new Date();

await client.actionService.createAction(
  create(CreateActionRequestSchema, {
    action: {
      id: "isr-collect-alpha",
      name: "ISR Collection Alpha",
      type: "isr_collection",
      scope: ActionScope.TASK,
      state: ActionState.ASSIGNED,
      priority: ActionPriority.HIGH,
      requestedBy: {
        id: "ops-cell-alpha",
        type: PrincipalType.USER,
      },
      assignedTo: {
        id: "uav-shadow-07",
        type: PrincipalType.OBJECT,
      },
      authorizedBy: {
        id: "s2-battle-captain",
        type: PrincipalType.USER,
      },
      intent: {
        purpose: "Observe NAI 3 before the convoy crosses phase line BLUE",
        method: "Maintain a collection orbit with EO/IR coverage",
        endState: "Report movement or changes near the route",
      },
      objectLinks: [
        {
          objectId: "link16-track-47210",
          type: ObjectLinkType.TARGET,
        },
      ],
      provenance: {
        name: "ops-center-01",
        updatedAt: timestampFromDate(updatedAt),
      },
    },
  }),
);
curl -X POST "${RDP_SERVER_URL}/api/v1/wdm/actions" \
  -H "X-API-KEY: ${RDP_API_KEY}" \
  -H "Content-Type: application/json" \
  --json @- <<JSON
{
  "action": {
    "id": "isr-collect-alpha",
    "name": "ISR Collection Alpha",
    "type": "isr_collection",
    "scope": "ACTION_SCOPE_TASK",
    "state": "ACTION_STATE_ASSIGNED",
    "priority": "ACTION_PRIORITY_HIGH",
    "requestedBy": {
      "id": "ops-cell-alpha",
      "type": "PRINCIPAL_TYPE_USER"
    },
    "assignedTo": {
      "id": "uav-shadow-07",
      "type": "PRINCIPAL_TYPE_OBJECT"
    },
    "authorizedBy": {
      "id": "s2-battle-captain",
      "type": "PRINCIPAL_TYPE_USER"
    },
    "intent": {
      "purpose": "Observe NAI 3 before the convoy crosses phase line BLUE",
      "method": "Maintain a collection orbit with EO/IR coverage",
      "endState": "Report movement or changes near the route"
    },
    "objectLinks": [
      {
        "objectId": "link16-track-47210",
        "type": "OBJECT_LINK_TYPE_TARGET"
      }
    ],
    "provenance": {
      "name": "ops-center-01",
      "updatedAt": "2026-05-27T21:31:04Z"
    }
  }
}
JSON