Navigating to API Path Using http_request

I am trying to build a REST API on ICP.

It seems that you can do this according to Is it possible to build a REST API in a Canister?.

I am testing out the example that allows for an API call using a specific query path: examples/motoko/http_counter at master · dfinity/examples · GitHub.

In the code, in the http_request, if the path URL is ‘/stream’, then it returns a status, body, etc.

What is the full URL that I would use to navigate to /stream?

On local, I attempted but it returned a 404:

http://[canisterId].localhost:4943/stream

I see that when I test out the Candid UI, it is sending a request to:
http://127.0.0.1:4943/api/v2/canister/[canisterId]/query

Any pointers would help. Thank you in advance!

If you call http_request directly from candid ui you are going straight to the replica. If go want to pull the webpage from your browser you just use the url and the boundary node calls that query for you and pipes the result thru http.

Hard to say why you got a 404. Maybe it wasn’t deployed? Or wrong canister id? Did you get a response in candid ui?

1 Like

Thank you so much for your response!

Here is my goal:

I would like to obtain a GET API with a standard endpoint. Ideally, I would like to access this endpoint using a format such as http://[canisterId].localhost:4943/stream.

After reviewing HTTPS interface specification, it looks like I can send a POST request /api/v2/canister/<effective_canister_id>/query with the function details in the body. I tried this but I was unable to get a result.

curl --location 'http://127.0.0.1:4943/api/v2/canister/br5f7-7uaaa-aaaaa-qaaca-cai/query' \

--header 'Content-Type: application/x-www-form-urlencoded' \

--data-urlencode 'method_name=http_request' \

--data-urlencode 'request_type=request' \

--data-urlencode 'canister_id=br5f7-7uaaa-aaaaa-qaaca-cai' \

--data-urlencode 'nonce=ba' \

--data-urlencode 'sender=aaaa' \

--data-urlencode 'ingress_expiry=1706993153000'

I assume this is what you mean by “pull the webpage from your browser you just use the url and the boundary node calls that query for you and pipes the result thru http.”

I’ll dig in more. Any feedback that you have would be appreciated!

If http://[canisterId].localhost:4943/stream does not work, then maybe http://localhost:4943/stream?canisterId=[canisterid] works instead. But unless you’re using Safari both should work. You can see how we do it in CI with curl right here: curl --fail -vv http://localhost:"$PORT"/new_file.txt?canisterId="$ID"

The /api/v2 endpoint is not what you want to use for a REST API that you talk to via HTTP. It’s meant for use with an agent.

(Hopefully) stupid question: You’re deploying your canister to the local network, right? If you deploy to --network ic then you’d have to hit <canister id>.icp0.io instead

1 Like

Hey, if you would like to build a REST API easily, you can always use one of the following HTTP routers:

Mokoto - GitHub - krpeacock/server: Motoko Http Server (wip)
Rust - GitHub - pu0238/pluto: HTTP framework designed for the needs of the internet computer network. When entering editing and updating data

2 Likes

Thank you so much for the suggestion. Is there any technical superiority in using these HTTP routers?

I don’t know about pluto, but with Motoko Server you don’t have to deal with certification yourself, which can be a big hassle

1 Like

Did you try using Azle? Azle recently released the possibility to build API Rest, try to start using this example: https://github.com/demergent-labs/azle/tree/main/examples/express

2 Likes

@princess_eth

I managed to get a query response using https://icp-api.io/api/v2/canister
example built from mobile app using setup from GitHub - kosta-bity/IcpKit: IcpKit.swift
url format: https://icp-api.io/api/v2/canister/{CANISTER-ID}/query
have yet to be able to get to submit data to a canister, only have been able to read a function that returns a Nat value

POST request data is sent with format “application/cbor”

http request builder:

hope this helps - still trying to figure this out myself

Nice! As @Severin mentioned, you should avoid using https://icp-api.io/api/v2/canister as it is only meant for the agent to use.

Have you looked into using http_response function? Maybe @kosta, the founder of ICPKit, can provide more insight on how to do this on ICPKit.

This whole website is served off of Motoko server, and the greeting is handled via REST POST requests instead of an agent.

https://qg33c-4aaaa-aaaab-qaica-cai.ic0.app/

I also think that Azle with Express is going to be exciting, although I don’t think they’ve solved certification yet

Thank you. My code was perfectly fine but I was passing in the wrong canister Id the entire time. I figured out that I should have done [id].localhost:4943/stream instead of [canisterId].localhost:4933/stream.

I realized that the id refers to the canister id and canisterId refers to the Candid UI id. I asked another question about that here: What is the difference between canisterId and id?.

Hopefully, this helps another developer!