Authorization & Security
The authorization flow, scopes, managing authorizations, and the security model for agrirouter integrations
Before an application can exchange data through agrirouter, the account owner must authorize the connection. The user grants the application permission to act on their behalf via a consent page; subsequent API calls are authenticated with the application's own client credentials token and authorized against the stored consent record. The flow uses OAuth 2.0 primitives, but it diverges from the textbook consent flow in one important way: no user-specific token is returned to the application.
Discovery via Deep URL
Before the authorization flow begins, the user needs a way to find your application and initiate the connection. This is where the Deep URL comes in.
When you register your application with agrirouter, you provide a Deep URL: an HTTPS URL pointing to your application's connection page where end users sign up or start a new agrirouter connection. This URL is stored on your application record and displayed in the agrirouter Solution Finder (the catalog of available integrations).
The typical flow is:
- An end user browses the agrirouter Solution Finder and finds your application
- They click Connect
- Their browser opens your Deep URL in a new tab
- Your application takes over, typically starting the OAuth authorization flow described below
The Deep URL should point as close as possible to the connection entry point of your application and must be a stable, publicly accessible HTTPS URL.
Before kicking off the authorization flow, confirm that the user intends to start an agrirouter connection. Auto-redirecting on page load leads to dropped connections and confused users; always require an explicit action (a button click or confirmation dialog) before starting the flow.
The full path from discovery to authorization: the user finds your app in the Solution Finder, clicks Connect, lands on your site, confirms they want to connect, and your application redirects them into the authorization flow.
All applications require user authorization before they can create endpoints.
Authorization Flow
The flow uses OAuth 2.0 redirect mechanics and a consent page, but no authorization code or user token is returned to the application. The authorization is recorded server-side and validated on every subsequent API call.
Application constructs the authorization URL
The application redirects the user's browser to agrirouter's authorization endpoint:
https://app.agrirouter.com/api/authorize?client_id={clientId}&scope={scope}&state={state}&redirect_uri={uri}The URL parameters are:
| Parameter | Required | Description |
|---|---|---|
client_id | Yes | The OAuth client ID assigned to your application during registration |
scope | No | The permissions being requested (for example, endpoints:manage). Defaults to endpoints:manage if omitted. |
state | No | An opaque string that agrirouter passes back unchanged in the redirect. Use it to prevent CSRF attacks and correlate the response with the request. |
redirect_uri | No | The URL where agrirouter redirects the user after authorization. Must match the URI registered for your OAuth client. |
User reviews and approves the connection
If the user is not already logged in, they are prompted to authenticate first. Once authenticated, the client_id is validated, the application details are resolved, and a consent page is displayed. The user sees the application's name and the requested scope.
The user has two choices:
- Connect: grants the application the requested permissions
- Reject: denies the request and returns the user to the application
The authorization is created and the user is redirected back
When the user clicks Connect, an authorization record is created linking the application to the user's account with the requested scope. The browser is then redirected back to the application's redirect_uri.
On approval:
| Parameter | Description |
|---|---|
state | The same state value the application sent in the authorization URL |
tenant_id | The tenant ID of the end user account the user selected on the consent page. Use this value as the x-agrirouter-tenant-id header on subsequent API calls acting on this user's behalf. |
The application should verify the state parameter matches the original value to prevent CSRF attacks, then store tenant_id for later API calls.
On rejection:
| Parameter | Description |
|---|---|
error | access_denied: the user denied the authorization request |
state | The same state value the application sent in the authorization URL |
No tenant_id is returned on rejection, since no tenant was selected.
Application can now manage endpoints
After verifying the state parameter, the application knows the user has granted permission. The application uses its client credentials token, which it can obtain independently at any time (see Access Tokens), to call the gateway API. The gateway verifies that a valid authorization record exists before processing requests like endpoint creation (see Endpoint Creation).
The legacy authorization flow uses a different URL pattern (/application/{applicationId}/authorize) and returns a registration code with a cryptographic signature that must be verified before the legacy onboarding request. If you are working with the legacy API, see Legacy API for details.
Scopes
Scopes define the permissions an application requests from the user. Each authorization is tied to a specific scope.
| Scope | Description |
|---|---|
endpoints:manage | Allows the application to create, configure, and delete endpoints on your behalf |
Additional scopes will be introduced in future versions of the API as more granular permissions become available.
Managing Authorizations
Users can view and manage all active authorizations in the agrirouter UI under Settings > Connections.
The management page shows:
- Authorized applications: each application's name, logo, and brand
- Endpoint count: how many endpoints the application has created in your account
- Scopes: the permissions granted to each application (toggle visibility via the display options)
- Sort options: sort by application name or by endpoint count
Revoking an Authorization
To revoke an application's access, click the Revoke button next to the application. A confirmation dialog will appear asking you to confirm the revocation.
Revoking an authorization removes the application's permission to manage endpoints in your account and deletes all endpoints the application created. The application will no longer be able to interact with your account.
Access Tokens
The application authenticates itself using the Client Credentials flow to obtain an access token. This is independent of user authorization; the application can request tokens at any time, for example at startup. The application sends its client_id and client_secret to the token endpoint:
POST https://api-oauth.agrirouter.com/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id={clientId}&client_secret={clientSecret}Alternatively, credentials can be sent via HTTP Basic authentication:
POST https://api-oauth.agrirouter.com/token
Authorization: Basic base64({clientId}:{clientSecret})
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentialsThe response contains an access token:
| Field | Description |
|---|---|
access_token | Bearer token used to authenticate API calls. |
token_type | Always Bearer |
expires_in | Token lifetime in seconds (default: 3600) |
The access token only proves the application's identity. When the application calls the gateway API (for example, to create an endpoint), the gateway separately verifies that a valid authorization record exists for this application and the user's account.
Renewal and refresh tokens
Access tokens expire (default lifetime: one hour). Request a new token before expiration; once expired, API calls will fail with 401 until a new token is obtained.
agrirouter does not issue refresh tokens. Because the application authenticates with its own client credentials, it can mint a new access token at any time by repeating the token endpoint call. This is functionally equivalent to a refresh token and offers the same security guarantees.
Treat the access token as opaque. Do not attempt to verify, decode, or introspect it; the token format is not part of the public API and may change without notice.
Endpoint Creation
After the user grants authorization and the application has obtained an access token, it can create an endpoint within the user's agrirouter account. The application sends a PUT /endpoints/{externalId} request with:
- An external ID that uniquely identifies this particular application instance
- The access token obtained from the token endpoint
The endpoint is created and its endpoint identifier is returned. The application uses its existing client credentials token for all subsequent API calls against this endpoint.
The external ID should follow the URN format: urn:{company}:{application}:{instance-identifier} (for example, urn:farmplan:fmis:user-12345).
Each endpoint belongs to exactly one tenant (the end user's agrirouter account), and every endpoint-management call must carry that tenant ID in the x-agrirouter-tenant-id request header so the gateway can scope the operation correctly.
Deleting Endpoints
When an endpoint is no longer needed, it can be deleted from the agrirouter account:
- Via API: the application sends a
DELETE /endpoints/{externalId}request. - Via agrirouter UI: the end user deletes the endpoint manually from their account settings. When this happens, the creating application is notified via an
ENDPOINT_DELETEDSSE event; applications should listen for this event and clean up their local state when it arrives.
Deleting an endpoint removes it from all routes, deletes every message in its feed, and permanently removes it from the account.
Delete endpoint1 minConventions and Standards
A few conventions shape how your integration handles data:
Timestamps
All timestamps must be in UTC using ISO 8601 format (for example, 2024-03-15T14:30:00.000Z). agrirouter does not accept timestamps in local time zones.
External IDs
The recommended format for external IDs is a URN (Uniform Resource Name):
urn:{company}:{application}:{instance-identifier}For example: urn:farmplan:fmis:user-12345 or urn:acme:telemetry:device-serial-ABC.
URNs provide a structured, globally unique identifier format that is human-readable and easy to debug.
Differences from the Legacy API
If you previously integrated with the legacy agrirouter API, several concepts no longer apply:
- Mutual TLS (mTLS) and TLS client certificates are not used in the current API. Applications authenticate exclusively via the client credentials OAuth 2.0 flow described above.
- Router Devices are legacy only. You may still see "Router Devices" in the developer portal's settings; new integrations can ignore this feature.
- Time synchronization tolerance is no longer enforced. The legacy API rejected requests whose timestamps drifted by more than one minute; the current API has no such requirement.
- Base64 line-break and 1-based chunk-numbering conventions are no longer relevant. Binary payloads and sequence numbers follow standard conventions.
Security Best Practices
Store your client credentials (client_id and client_secret), access tokens, and endpoint IDs securely. Use encrypted storage, environment variables, or a secrets management system. Never commit credentials to version control or log them in plain text.
Always use a cryptographically random state parameter in authorization requests and verify it in the redirect. This prevents cross-site request forgery (CSRF) attacks.
The redirect_uri parameter is validated with an exact string match against the URI registered for your OAuth client. Query strings, trailing slashes, and case differences all count, so register the exact URI your application will send. Never include sensitive data in redirect URI query parameters, and always use HTTPS for your callback endpoints.
Your client_secret is used to authenticate your application when requesting access tokens. Treat it like a password: never expose it in client-side code, commit it to version control, or log it. Use server-side token exchange and store the secret in a secrets manager or environment variable.