Build a gRPC RTD service

Integration Partners
Last Updated: August 12, 2026

This topic covers implementing a gRPC-based real-time data integration service. All new containers should be built for gRPC.

gRPC integration build guide

Complete the following steps to set up the proto files and generate the language-specific bindings your container requires. This uses protoc, the Protocol Buffers compiler, which converts .proto schema files into language-specific code. Installation instructions are available at grpc.io/docs/protoc-installation.

  1. Download the official OpenRTBClosed An open industry standard for communication between buyers and sellers of online advertising in real-time bidding auctions. It's published by the IAB. 2.6 Protocol Buffers specification from the IAB Tech Lab's openrtb2.x repository.

  2. Clone the ARTF reference implementation repository, which contains the Makefile, build scripts, and proto files referenced in the steps below.

  3. Generate the language-specific OpenRTB and gRPC bindings:

    1. Install make and protoc v27 or later. This is required for edition = "2023" support; the version in most base package managers is too old and errors on --experimental_editions.

    2. Install the language plugins. For example, for Go:

      go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
      go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
    3. Open the Makefile and choose the languages under LANGUAGES.

    4. Run make bindings. Plain make builds the reference agent, not the bindings.

  4. Alternatively, skip generation and use the pre-generated Go bindings included in the repository under pkg/pb/ (pkg/pb/artf, pkg/pb/openrtb).

Classification endpoint

Partners must expose an endpointClosed A URL which is configured to interact with a server in a specific way. accessible through a gRPC request following the agentic RTBClosed Real-Time Bidding (RTB). The automated buying and selling of inventory for advertisements in real time, which is within milliseconds of an individual user loading a site. Protobuf Schema downloaded with your build files.

The SLA for Index Exchange (Index) to use your response in auction processing is 5 milliseconds. No more than 3% of requests are allowed to exceed the tmax timeout value. If more than 3% of requests time out, traffic to your container is automatically throttled and Index may lower QPSClosed Queries Per Second (QPS). The number of bid requests a DSP processes per second. Also known as impressions per second. accordingly. Calls use keepalive connections to minimize network overhead.

Response codes

Standard gRPC status codes should be returned.

Circuit breaker logic

If Index receives any status code other than OK, or more than 3% of requests have exceeded an internal timeout value of 30ms, Index's circuit breaker triggers and requests to your container are throttled. Requests that time out also trigger this logic.

Circuit breaker logic protects both Index and partner systems from cascade failures. Once error rates return to nominal levels, measured over a rolling window, circuit breakers reopen and regular traffic volume resumes automatically. No action is required from your side during recovery.

Note: The circuit breaker uses a 30ms internal timeout for both gRPC and HTTP integrations. The 5ms figure is the SLA for your response to be used in auction processing; the 30ms figure is the outer timeout after which Index treats the request as failed for circuit breaker purposes.

gRPC-supported lifecycle extension points and mutations

The following table summarizes all supported lifecycle extension points, the mutations available at each, and their paths. For full schema details and examples, see the Mutation reference.

Extension pointMutationSupported pathUse case

PublisherClosed The owner of a website or app where advertisements are served. request

ACTIVATE_SEGMENTS

/user/data/segment

Activate a list of segment IDs for a given request.

Publisher request

ACTIVATE_DEALS

/imp/<impID>

Activate a dealClosed A private auction that allows media owners to offer specific inventory directly to selected buyers identified by a deal ID. Terms are negotiated and are agreed upon before the auction occurs. for a specific impression. One deal ID per mutation; use separate mutations for multiple deal IDs.

Publisher request

SUPPRESS_DEALS

/imp/<impID>

Suppress a deal for a specific impression. One deal ID per mutation; use separate mutations for multiple deal IDs.

Publisher request

ADJUST_DEAL_FLOOR

/imp/<impid>/deal/<dealid>

Adjust the bid floorClosed A pricing control used by media owners and exchanges to set a minimum sale price on inventory. of a specific deal.

Publisher request

ADD_CIDS

/site/content/data or /app/content/data

Add a list of Extended Content IDs to the site or app content object.

DSPClosed Demand-Side Platform (DSP). A software platform that automates bidding decisions in real-time and efficiently connects buyers and audiences through an ad exchange or SSP. Also known as a buy-side platform. bid responseClosed An OpenRTB response that is sent by the DSP in response to the SSP's or ad exchange's bid request. It is an event directed back to the seller expressing a valuation for the request and conditions of sale.

BID_SHADE

/seatbid/<seatID>/bid/<bidID>

Recommend a lower transaction price for a DSP bid.

What your container receives

At the Publisher Request extension point, your GetMutations handler receives an RTBRequest whose bid_request field holds the full privacy-safe OpenRTB payload. For the fields included in that payload, see the Publisher request payload reference. Index calls GetMutations in real time during auction processing, once per extension point.

Two other RTBRequest fields matter for every call:

  • tmax is the maximum number of milliseconds Index waits for your response. Treat it as a hard deadline.

  • applicable_intents is the list of mutation intents Index accepts on that call. Filter your mutations to only these; a mutation whose intent is not in applicable_intents is silently discarded.

Note: The bid_response field is empty at the Publisher Request extension point. It is only populated when lifecycle is LIFECYCLE_DSP_BID_RESPONSE. Note that device.ip, device.geo.lat, device.geo.lon, and device.geo.zip may be anonymized, masked, or withheld depending on the request user's privacy settings. See the Publisher request payload reference for the full list of modifications.

The following is an example of a complete RTBRequest at the Publisher Request extension point, in protojson format:

{
   "id": "2545D87B17C8853B",
   "lifecycle": "LIFECYCLE_PUBLISHER_BID_REQUEST",
   "tmax": 5,
   "applicable_intents": [
      "ACTIVATE_SEGMENTS", "ACTIVATE_DEALS", "SUPPRESS_DEALS",
      "ADJUST_DEAL_FLOOR", "ADD_CIDS"
   ],
   "bid_request": {
      "id": "2545D87B17C8853B",
      "imp": [{
         "id": "1",
         "banner": { "w": 300, "h": 250, "pos": 1, "format": [{ "w": 300, "h": 250 }] },
         "bidfloor": 0.5,
         "ext": { "gpid": "/1234567/home/mpu/atf", "sid": "abc123" }
      }],
      "site": {
         "id": "12345", "domain": "example.com",
         "page": "https://example.com/section/",
         "publisher": { "id": "555555", "domain": "example.com", "name": "Publisher Name" }
      },
      "device": {
         "connectiontype": 2, "devicetype": 2, "dnt": 0,
         "ip": "2001:db8::", "language": "en", "lmt": 0,
         "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/114.0.0.0"
      },
      "regs": { "coppa": 0 },
   }
}

Note: lifecycle, id, tmax, and bid_request are required on every RTBRequest and must be set on every call. In particular, bid_request is required even at LIFECYCLE_DSP_BID_RESPONSE, where you operate on bid_response. Omitting it fails to marshal. Echo id back unchanged in RTBResponse.id.

What your container returns

Your GetMutations handler returns an RTBResponse containing the following fields:

FieldPurpose

id

Echo the id from the request.

mutations

The list of mutations you want applied. Return an empty list if you have nothing to contribute.

metadata

api_version (your container version) and model_version (current model version).

Implementation pattern

Structure your handler as follows:

  1. Respect tmax. Set a deadline on any inner work using context.WithDeadline.

  2. Read signals from bid_request, and from bid_response on the post-bid path.

  3. Filter by applicable_intents. Only build mutation types that are eligible for this call.

  4. Build mutations per the schema (intent, path, op, value). Use one mutation per entity.

  5. Return the response with the same id, your mutations, and metadata.

Next: Implement whichever mutations you need. See Mutation reference for the schema of all six, and Implementing bid shading for additional depth if bid shading is one of them. If you are deploying in Index Cloud, continue to Building your container to package your container, then validate it with Using the Index testing tool. If you are hosting the service yourself, validate your implementation with Using the Index testing tool; your container is ready to deploy to your own infrastructure once it passes.