Docs

Your First Endpoint

Step-by-step guide to authenticating your application, obtaining user authorization, and creating your first agrirouter endpoint

An endpoint is your application's representation within agrirouter. It represents a single user account of your application connected to a specific agrirouter account. Before you can send or receive any data, you need to authenticate your application, obtain user authorization, and create an endpoint.

This page covers the full setup, from your first access token to a working endpoint.

This page covers the authorization and endpoint-creation flow for cloud_software and virtual_communication_unit endpoints, which use OAuth2 client credentials for application authentication and a browser-based consent flow for user authorization. If you are building a physical Communication Unit (CU) such as a terminal or telemetry box, use the legacy API instead. See the CU integration guide.

Prerequisites

Before you begin, make sure you have:

  • A developer account with an application version that is at least in Approved for Testing state (see Setup Application)
  • Your application credentials: client_id and client_secret (request from the agrirouter team)
  • A registered redirect URI for your application (configured during application registration)
  • The environment URLs for your target environment (see Environment URLs)
  • A tool for making HTTP requests (e.g., cURL, Postman, or your application code). You can also use the built-in API testing feature in these docs.

How the pieces fit together

Creating an endpoint requires three independent steps, which map to the authorization flow:

  1. Authenticate your application: obtain an access token using your client credentials. This can happen at any time (for example, at application startup).
  2. Get user authorization: redirect the user to agrirouter's consent page so they grant your application permission to manage endpoints in their account. This is done once per user.
  3. Create the endpoint: call the gateway API with your access token. The gateway checks that the user has authorized your application before processing the request.

Setting up authentication and authorization

Obtain an access token

Your application authenticates itself using the OAuth2 Client Credentials flow. This is independent of any user interaction: you can request a token at any time, for example at application startup.

curl -X POST https://api-oauth.agrirouter.com/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials&client_id={yourClientId}&client_secret={yourClientSecret}"

The URL above is for the production environment. If you are working with the QA environment, use the corresponding QA URL. See Environment URLs for the complete list.

The response contains a signed JWT (JSON Web Token):

{
  "access_token": "eyJhbGciOiJFUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3600
}

Only the value of the access_token field is the Bearer token. Do not include the full JSON object or the surrounding quotes when you set the Authorization header:

Authorization: Bearer eyJhbGciOiJFUzI1NiIs...

Store this token and include it on all subsequent API requests. Request a new token before it expires. You should only use the information in expires_in to schedule the next refresh and you should not try to parse the token itself. We do not guarantee the structure or content of the token, you need to treat it as opaque (pass it as-is, without any transformation or introspection).

The access token only proves your application's identity. It does not grant permission to act on any user's behalf. That requires user authorization (next step).

When a user wants to connect your application to their agrirouter account, redirect their browser to agrirouter's consent URL:

https://app.agrirouter.com/api/authorize?client_id={yourClientId}&redirect_uri={yourRedirectUri}&scope=endpoints:manage&state={randomStateValue}
ParameterRequiredDescription
client_idYesYour OAuth client ID
redirect_uriYesMust exactly match (string equality) the URI registered for your application. If it is missing or does not match, the consent page shows an error and the user cannot continue.
scopeNoDefaults to endpoints:manage, the permission to create and manage endpoints.
stateRecommendedA cryptographically random string echoed back on the redirect. Use it to prevent CSRF attacks and to correlate the response with the originating request.

The user sees a consent page where they can Connect or Reject your application. If client_id or redirect_uri is missing, malformed, or does not match the registered values, the consent page renders an error instead of the consent prompt — the user has no way to grant authorization in that case, so make sure both parameters are present and correct before redirecting.

Handle the redirect back

After the user makes a choice, the browser is redirected back to your redirect_uri:

On approval:

https://yourapp.com/callback?state={randomStateValue}&tenant_id={userTenantId}

On rejection:

https://yourapp.com/callback?error=access_denied&state={randomStateValue}

Your application should:

  1. Verify the state parameter matches the value you originally sent (to prevent CSRF attacks)
  2. Check for the error parameter. If present, the user denied the request.
  3. Store the tenant_id parameter (approval only). This is the tenant ID of the end user account the user selected on the consent page. Use it as the x-agrirouter-tenant-id header on every subsequent API call you make on this user's behalf.

No authorization code or token is returned in the redirect. The authorization is recorded server-side by agrirouter. Your application only needs to know the user approved, and the tenant ID of the account they selected. After that, your existing client credentials token is all you need to call the API.

Creating your endpoint

With a valid access token and user authorization in place, you can now create an endpoint.

Get your tenant ID

The tenant ID identifies the end user account your endpoint will belong to. Use it as the x-agrirouter-tenant-id request header on every call to PUT /endpoints/{externalId} and the other endpoint-management operations for this user.

You can pick up the tenant ID from either of two sources, depending on which side of your application is driving the next step:

  • From the redirect query parameter — the tenant_id value on the authorization callback shown above. This is the natural choice when the frontend continues straight into endpoint creation, for example when the same browser session calls back to your backend with the parsed query.
  • From the AUTHORIZATION_ADDED SSE event — delivered on the GET /events stream when the user grants the authorization, carrying the same tenant_id together with the granted scope. This is the natural choice when a backend keeps a long-lived SSE connection and reacts to authorizations there, without taking a dependency on the redirect URL.

Both sources surface the same authorization. Pick the one that fits your architecture, or use both — for example, the frontend stores the tenant ID for the immediate next call and the backend independently picks it up from the event to update its own state.

To list every tenant your application is currently authorized for (for example, on application startup or after a crash), call GET /tenants.

Your application's own developer-account tenant ID (used to sign into the developer portal) is a separate value issued with your OAuth credentials. That is not the tenant ID you pass on per-user API calls.

Treat the access token as opaque. Do not decode the JWT to look up a tenant ID or any other account information, since the token format is an implementation detail and may change without notice.

Tenant IDs4 min

Choose an external ID

Every endpoint needs an external ID, a unique identifier your application uses to reference this endpoint instance. Use the URN format:

urn:<your-domain>:<application>:<instance-identifier>

For example:

urn:mycompany.com:farmapp:user-12345

External IDs are unique within the scope of a tenant (account). This means the same external ID cannot be used twice in the same account, even by different applications.

Create the endpoint

Send a PUT request to the endpoints API with your access token and chosen external ID. The example below focuses on the fields you will edit most often; open the API reference for the full schema and to try it against your own data.

PUT/endpoints/{externalId}Open API reference

Creates a new endpoint for this tenant. The first call for a given externalId creates the endpoint; subsequent calls replace its configuration.

Request headers
Authorization: Bearer eyJhbGciOiJFUzI1NiIs...
Content-Type: application/json
x-agrirouter-tenant-id: 12345678-abcd-ef01-2345-6789abcdef01
Request body
"name": "FarmApp user-12345",
"application_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"software_version_id": "f0e1d2c3-b4a5-6789-0abc-def123456789",
"endpoint_type": "cloud_software",
"capabilities":
"message_type": "iso:11783:-10:taskdata:zip",
"direction": "SEND_RECEIVE"
},
"message_type": "img:png",
"direction": "SEND_RECEIVE"
}
],
"subscriptions":
"message_type": "iso:11783:-10:taskdata:zip"
}
]
}
Response 200
"id": "9f8e7d6c-5b4a-3210-fedc-ba0987654321",
"external_id": "urn:mycompany.com:farmapp:user-12345",
"application_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"software_version_id": "f0e1d2c3-b4a5-6789-0abc-def123456789",
"endpoint_type": "cloud_software",
"tenant_id": "12345678-abcd-ef01-2345-6789abcdef01",
"capabilities":
"message_type": "iso:11783:-10:taskdata:zip",
"direction": "SEND_RECEIVE"
},
"message_type": "img:png",
"direction": "SEND_RECEIVE"
}
]
}

The request body includes:

  • name (optional): a human-readable label shown in the agrirouter web interface, 1-200 characters of letters, digits, spaces, and -, _, ., ,, :. If you omit it, agrirouter generates one for you. Names do not have to be unique, and the user can rename the endpoint in the web interface; once they do, later PUT calls will not overwrite their choice.
  • application_id and software_version_id: the UUIDs of your registered application and its version (received during application registration in Setup Application)
  • endpoint_type: the type of endpoint, either cloud_software or virtual_communication_unit (see Endpoint Types)
  • capabilities: the message types your endpoint can handle, each with a direction (SEND, RECEIVE, or SEND_RECEIVE)
  • subscriptions: the message types your endpoint wants to receive through the publish and subscribe model

For the full conceptual model, see Capabilities and Subscriptions on the Messaging concepts page.

A successful response returns the endpoint details, including the agrirouter-generated endpoint ID, a UUID you will need when sending messages.

Store the id (agrirouter endpoint UUID) and tenant_id from this response. You will need both when sending messages: the API uses these agrirouter-generated UUIDs, not the external ID.

If the user has not authorized your application, this request will fail. The gateway checks that a valid authorization record exists for your application and the user's account before creating the endpoint.

Verify in the agrirouter UI

Log in to the agrirouter UI and navigate to your account's endpoint list. Your newly created endpoint should appear with:

  • The name of your application
  • The capabilities you configured
  • An active status

Capabilities and subscriptions in depth

The capabilities and subscriptions arrays you sent above decide which message types your endpoint can handle and which published messages it wants to receive. Both are required on every PUT /endpoints/{externalId} request. Each call replaces the previous configuration with the values you send, so always include the complete set.

Capabilities are not routes

Declaring a SEND or RECEIVE capability and a subscription only tells agrirouter what your endpoint is willing to handle. For any message to actually flow between two endpoints, the account owner has to configure a route for the matching information type in the agrirouter UI. Your PUT /endpoints/{externalId} call does not create routes, and direct addressing with x-agrirouter-direct-recipients does not bypass this: a direct send to a recipient with no route comes back as a 400.

For a self-test, log in to a test account where you control routing and configure routes between your endpoints in the agrirouter UI before exercising send and receive flows. Plan for this before you start coding the send path; if the routes are not in place, your first send will fail or silently no-op (publish to nobody returns a 200 with no delivery).

Messaging Concepts9 min

What you have accomplished

You now have:

  • An access token that authenticates your application with agrirouter
  • User authorization granting your application permission to manage endpoints
  • An active endpoint with declared capabilities and subscriptions

For the authorization model in depth, see the authorization and security concepts page.

Authorization & Security9 min

For the full endpoint lifecycle, including updates and revocation, see the endpoints concepts page.

Endpoint Concepts4 min

Next steps

Your endpoint is ready to exchange data. Continue to the next page to send your first message.

Send Your First Message4 min

On this page