Calling Your Services' APIs
Overview
Once you have written and deployed your application, chances are you will want to interact with it from the outside world--either via a UI or directly through REST API calls. In this section, we will cover how to call your services' APIs from outside the service, and how to authenticate those calls.
Calls between flows within the same service can be done using normal Python function calls. There is no need to use HTTP calls or authentication for intra-service communication.
Set Up Authentication
Oryonix lets you control how API calls to your services are authenticated. You can configure API keys for each environment using the onix environment auth create command.
API keys are useful when you do not have a UI and need to call your APIs directly. They may also be a good choice if you want to test your APIs yourself before releasing them to end users.
Generate an API Key
Ensure you are on the Git branch linked to your target environment before running the following command.
onix environment auth create --name "API key" --type api_key
The above command will generate an API key for the environment. This API key will be shown only once, so make sure you save it securely.
Authentication Flow
To authenticate your API calls, pass the key as a bearer token in the Authorization header:
curl https://your-service-url/greet -H "Authorization: Bearer <api-key>"
Call REST APIs Synchronously
You can call your services' REST APIs synchronously using any HTTP client, such as curl, Postman, or your own custom client. Just make sure to include the appropriate authentication headers as described above.
When you deploy an application into an environment, Oryonix will create a public URL for that environment. You can copy the URL for your environment from the "Environment" section at the top of the application's dashboard. For example, if your environment URL is https://your-app.production.oryonix.app, and you have a service with an endpoint /greet, you can call it like this:
curl https://your-app.production.oryonix.app/greet \
-H "Authorization: Bearer <api-key>" \
-H "Content-Type: application/json" \
-d '{"name": "Alice"}'
The request and response bodies should look exactly like what is described in your service's OpenAPI spec file. Oryonix will transparently validate the request and response against the OpenAPI spec, and route it to the appropriate flow based on the operationId defined in the spec for that route.
Use Idempotency Keys to Avoid Duplicate Requests
If you want to ensure that a request is only processed once, even if it is sent multiple times (e.g., due to retries), you can use the Idempotency-Key header. This is especially useful for operations that have side effects, such as creating a new resource or processing a payment.
curl https://your-app.production.oryonix.app/greet \
-H "Authorization: Bearer <api-key>" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: \"<unique-idempotency-key>\"" \
-d '{"name": "Alice"}'
If the same Idempotency-Key is received again, the request will not be duplicated. Instead, the Onix platform will respond in one of a few ways:
- If the original request is still being processed, the second request will block and return the same result as the original request, unless the second request exceeds the timeouts as described below.
- If the original request has already completed, the second request will return the same response as the original request, without re-executing the flow.
- If an Idempotency-Key is reused for a different request, the second request will fail with a
422 Unprocessable Contentstatus code, indicating that the Idempotency-Key is not unique.
Idempotency keys are unique to each type of operation exposed by the service's API--you may reuse the same key with different endpoints, so long as they have different operationIds in the service's OpenAPI spec. Keys will expire (and become available for reuse) after an implementation-defined amount of time, guaranteed to be at least 5 minutes, but possibly much longer (90 days or more).
If you do not specify an idempotency key yourself, the Onix platform will generate a new, unique key for each request, formatted as a UUID. This means that if you do not provide an idempotency key, each request will be treated as unique and will be processed independently.
When retrying a request with the same Idempotency-Key, make sure to use the same URL, parameters, and request body as the original request. If the same key is used with different request data, the Onix platform will reject the request with a 422 Unprocessable Content status code.
The content of the idempotency key itself is opaque to the Onix platform, so you can generate it in any way that makes sense for your application. However, in keeping with the current draft standard for the Idempotency-Key header, keys must be specified as valid RFC 8941 strings whose decoded content is no longer than 255 bytes.
Here are some examples of valid and invalid headers:
# Valid: the key is: my-unique-key
Idempotency-Key: "my-unique-key"
# Valid: the key is: my-"unique"-key\
Idempotency-Key: "my-\"unique\"-key\\"
# Invalid: the key contains non-ASCII characters
Idempotency-Key: "my-ünîqüé-kéy"
# Invalid: quotes are missing around the key
Idempotency-Key: my-unique-key
Idempotency keys may be logged by the Onix platform for debugging and auditing purposes, so avoid including any sensitive information in the keys.
Launch REST APIs Asynchronously
Asynchronous requests and responses, including the Onix-Respond-After and Onix-Cancel-After headers, are not yet implemented.
If you want to call your services' APIs asynchronously, Oryonix provides custom HTTP headers for controlling request execution and checking request status, and may return additional HTTP headers and status codes not defined in your OpenAPI spec to indicate the status of the request.
To launch an asynchronous request, make the request like normal, but provide additional headers to tell the Onix platform that you want the request to be handled asynchronously:
curl https://your-app.production.oryonix.app/greet \
-H "Authorization: Bearer <api-key>" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: \"<unique-idempotency-key>\"" \
-H "Onix-Respond-After: PT1S" \
-H "Onix-Cancel-After: PT5S" \
-d '{"name": "Alice"}'
In the above example, we are calling the /greet endpoint with the Idempotency-Key header, and with additional Onix-Respond-After and Onix-Cancel-After headers. Each of these headers plays a distinct role in the request handling process.
Onix-Respond-After
This header is not yet implemented.
The Onix-Respond-After header tells the Onix platform to respond after a specified duration even if the request hasn't completed. The value of the Onix-Respond-After header is a duration in ISO 8601 format (e.g., PT1S for 1 second).
Just as with the Idempotency-Key header, the platform will respond differently depending on the state of the request:
- If the request is still being processed when the specified duration elapses, the platform will respond with a
202 Acceptedstatus code if this is the first time theIdempotency-Keyhas been used, or with a409 Conflictstatus code if theIdempotency-Keyhas already been used. - If the request completes before the specified duration elapses, the platform will respond with the final response of the request, as if the
Onix-Respond-Afterheader had not been included.
If a zero duration is specified (e.g., PT0S), the platform will respond without waiting, as described above. If the header is omitted entirely, the platform will wait until the request is complete (or canceled as described below) before responding, up to an implementation-defined maximum duration (after which the platform responds as described above).
Onix-Cancel-After
This header is not yet implemented.
The Onix-Cancel-After header tells the Onix platform to cancel the request if it has not completed after a specified duration. The value of the Onix-Cancel-After header is also a duration in ISO 8601 format (e.g., PT5S for 5 seconds).
The timeout specified in the Onix-Cancel-After header is only applied on the first request--if the same request is retried, any Onix-Cancel-After header in the retried request will be ignored. This means it is not possible to extend the processing time of a request by retrying with a new Onix-Cancel-After header.
A zero duration (e.g., PT0S) is always rejected with 400 Bad Request, since it would not make sense to cancel a request immediately. If the header is omitted or exceeds an implementation-defined maximum duration, the platform will cancel the request after the maximum allowed duration.
Clients should set this value to a value less than the client's own internal timeout, or specify an Onix-Respond-After header that is less than that timeout.
If a request exceeds the requested duration, it will be forcibly terminated. Any pending or subsequent retries of the same request will receive a 504 Gateway Timeout status code.
Onix-Respond-After and Onix-Cancel-After operate independently. Onix-Respond-After bounds the maximum time the platform will wait before responding, and Onix-Cancel-After bounds the request processing time. If Onix-Cancel-After elapses before Onix-Respond-After does, the request will be terminated and a 504 Gateway Timeout status code will be returned--"in-progress" status codes like 202 Accepted or 409 Conflict will never be returned.
REST API Responses
In general, once a request has completed, the Onix platform will return the result verbatim as it was specified in the service's OpenAPI spec. The only exception to this is if a request is being processed or has timed out. However, the platform may also return additional HTTP headers to provide more information about the request--clients are free to ignore those headers if they do not need that information, but they may be useful for debugging or monitoring purposes.
Responses from Services
Once a request to a service completes, regardless of whether it succeeds or fails, the Onix platform will return the response as defined in the service's OpenAPI spec. This means that the status code, headers, and body of the response will match what is specified in the OpenAPI spec for that endpoint.
However, Onix will also provide the following additional headers in the response:
Idempotency-Key: The idempotency key associated with the request, either as provided by the client or generated by the platform.
Responses from the Onix Platform
If the service is still processing the request, or the request has been terminated, the Onix platform will respond on the service's behalf.
Any of the following status codes may be returned:
202 Accepted: The request has been accepted for processing, but the processing has not been completed. This will only be returned if the client specified anOnix-Respond-Afterheader and the specified duration has elapsed, or if the platform has determined that the request is taking too long to process and the client did not specify anOnix-Respond-Afterheader.409 Conflict: The request has been rejected because the sameIdempotency-Keyhas already been used for this request. Just like with202 Accepted, this will be returned only if theOnix-Respond-Afteror platform-defined timeouts have elapsed.422 Unprocessable Content: The request has been rejected because the sameIdempotency-Keyhas already been used for a different request. If the client wants to retry, it should use a differentIdempotency-Keyfor this request.504 Gateway Timeout: The request has been terminated because it has exceeded the duration specified in theOnix-Cancel-Afterheader, or because the platform has determined that the request is taking too long to process and the client did not specify anOnix-Cancel-Afterheader.
In general, clients implementing retry logic can treat 202 Accepted and 409 Conflict responses the same: the request is still in progress. The only distinction is that a 202 Accepted response indicates that this is the first time the platform has seen this request, whereas a 409 Conflict response indicates that the platform has already seen this request.
In any case, the response will also contain the following headers:
- Idempotency-Key: The idempotency key associated with the request, either as provided by the client or generated by the platform.